diff --git a/PRODUCTNAME/Gemfile b/PRODUCTNAME/Gemfile index 07552db..31931fc 100644 --- a/PRODUCTNAME/Gemfile +++ b/PRODUCTNAME/Gemfile @@ -12,3 +12,6 @@ gem 'fastlane' gem 'cocoapods', '>=1.7.2' gem 'synx' gem 'nanaimo' + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) \ No newline at end of file diff --git a/PRODUCTNAME/README.md b/PRODUCTNAME/README.md index 67f1db6..c48bb89 100644 --- a/PRODUCTNAME/README.md +++ b/PRODUCTNAME/README.md @@ -1,16 +1,14 @@ # {{ cookiecutter.project_name }} -[![Develop](https://img.shields.io/badge/Hockey-Develop-green.svg)][develop-hockey] -[![Sprint](https://img.shields.io/badge/Hockey-Sprint-green.svg)][sprint-hockey] +[![AppCenter](https://img.shields.io/badge/AppCenter-Yes-blue)](https://appcenter.ms/orgs/APPCENTERORG/apps/APPCENTERAPP) [![CircleCI](https://circleci.com/gh/Rightpoint/{{ cookiecutter.company_name | replace(' ', '-') | lower }}-ios/tree/develop.svg?style=shield&circle-token=ZZCIRCLE_PROJECT_STATUS_KEYZZ)][circle-ci] [![codecov](https://codecov.io/gh/Rightpoint/{{ cookiecutter.company_name | replace(' ', '-') | lower }}-ios/branch/master/graph/badge.svg)](https://codecov.io/gh/Rightpoint/{{ cookiecutter.company_name | replace(' ', '-') | lower }}-ios) ## Development Process -All stories and bugs are tracked in [JIRA][]. Development occurs on branches that are tested with the `test` fastlane task once a PR is created. The PR is reviewed and then merged into the `develop` branch. This triggers the `develop` fastlane task which distributes a build to the [develop][develop-hockey] hockey app for testing and PO approval. At the end of a sprint, a `sprint-X` tag is manually created which triggers the `sprint` fastlane task which distributes a build to the [sprint][sprint-hockey] hockey app. +All stories and bugs are tracked in [JIRA][]. Development occurs on branches that are tested with the `test` fastlane task once a PR is created. The PR is reviewed and then merged into the `develop` branch. This triggers the `develop` fastlane task which distributes a build to the [develop][develop-appcenter] Appcenter app for testing and PO approval. At the end of a sprint, a `sprint-X` tag is manually created which triggers the `sprint` fastlane task which distributes a build to the [sprint][sprint-appcenter] Appcenter app. -[circle-ci]: https://circleci.com/gh/Rightpoint/{{ cookiecutter.project_name }}-ios +[circle-ci]: https://circleci.com/gh/Rightpoint/PRODUCTNAME-ios [JIRA]: https://raizlabs.atlassian.net/secure/RapidBoard.jspa?projectKey={{ cookiecutter.jira_key }} -[sprint-hockey]: https://rink.hockeyapp.net/apps/ZZHOCKEY_SPRINT_IDZZ -[develop-hockey]: https://rink.hockeyapp.net/apps/ZZHOCKEY_DEVELOP_IDZZ +[AppCenter]: https://appcenter.ms/orgs/APPCENTERORG/apps/APPCENTERAPP To get started, see [Contributing](#contributing) diff --git a/PRODUCTNAME/app/PRODUCTNAME.xcodeproj/project.pbxproj b/PRODUCTNAME/app/PRODUCTNAME.xcodeproj/project.pbxproj index de1401c..fcf6177 100644 --- a/PRODUCTNAME/app/PRODUCTNAME.xcodeproj/project.pbxproj +++ b/PRODUCTNAME/app/PRODUCTNAME.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 209BE2512051C768004CF0FF /* Actionable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 209BE2502051C768004CF0FF /* Actionable.swift */; }; 209BE2562051C90C004CF0FF /* actionable.swifttemplate in Resources */ = {isa = PBXBuildFile; fileRef = 209BE2552051C90C004CF0FF /* actionable.swifttemplate */; }; 209BE2592051CB4B004CF0FF /* Actionable+AutoConformance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 209BE2582051CB4B004CF0FF /* Actionable+AutoConformance.swift */; }; + 280520562371F60E003E1041 /* AppCenterConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 280520552371F60E003E1041 /* AppCenterConfiguration.swift */; }; 2D4FA8F51E8574F9006C38ED /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4FA8F41E8574F9006C38ED /* AppCoordinator.swift */; }; 2D4FA8F71E85752B006C38ED /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4FA8F61E85752B006C38ED /* Coordinator.swift */; }; 2D75C6C71E8EEAE900F2EB1D /* OnboardingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFF1CEC1E8944B900B1AD70 /* OnboardingCoordinator.swift */; }; @@ -79,7 +80,7 @@ ABF84FA81DCBFF84002DB24D /* TestEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABF84FA71DCBFF84002DB24D /* TestEndpoint.swift */; }; BE28092A1E802893006E50D5 /* Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2809271E802893006E50D5 /* Analytics.swift */; }; BE28092B1E802893006E50D5 /* AnalyticsPageNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2809281E802893006E50D5 /* AnalyticsPageNames.swift */; }; - BE28092C1E802893006E50D5 /* GoogleAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2809291E802893006E50D5 /* GoogleAnalytics.swift */; }; + BE28092C1E802893006E50D5 /* FirebaseAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2809291E802893006E50D5 /* FirebaseAnalytics.swift */; }; BE28092E1E8029D8006E50D5 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE28092D1E8029D8006E50D5 /* AnalyticsConfiguration.swift */; }; BE2809301E8038BE006E50D5 /* ContentTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE28092F1E8038BE006E50D5 /* ContentTabBarViewController.swift */; }; BE4C21EB1E81970A00645143 /* DebugMenuConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE4C21EA1E81970A00645143 /* DebugMenuConfiguration.swift */; }; @@ -144,6 +145,7 @@ 209BE2502051C768004CF0FF /* Actionable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actionable.swift; sourceTree = ""; }; 209BE2552051C90C004CF0FF /* actionable.swifttemplate */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = actionable.swifttemplate; sourceTree = ""; }; 209BE2582051CB4B004CF0FF /* Actionable+AutoConformance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Actionable+AutoConformance.swift"; sourceTree = ""; }; + 280520552371F60E003E1041 /* AppCenterConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCenterConfiguration.swift; sourceTree = ""; }; 2D4FA8F41E8574F9006C38ED /* AppCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = ""; }; 2D4FA8F61E85752B006C38ED /* Coordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = ""; }; 2D4FA8F81E8577B5006C38ED /* AuthCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthCoordinator.swift; sourceTree = ""; }; @@ -223,10 +225,9 @@ ABF84FA31DCBCD89002DB24D /* APIClientTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIClientTests.swift; sourceTree = ""; }; ABF84FA51DCBCEA1002DB24D /* Payloads.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Payloads.swift; sourceTree = ""; }; ABF84FA71DCBFF84002DB24D /* TestEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEndpoint.swift; sourceTree = ""; }; - BE2809251E802474006E50D5 /* PRODUCTNAME-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PRODUCTNAME-Bridging-Header.h"; sourceTree = ""; }; BE2809271E802893006E50D5 /* Analytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Analytics.swift; sourceTree = ""; }; BE2809281E802893006E50D5 /* AnalyticsPageNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyticsPageNames.swift; sourceTree = ""; }; - BE2809291E802893006E50D5 /* GoogleAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GoogleAnalytics.swift; sourceTree = ""; }; + BE2809291E802893006E50D5 /* FirebaseAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirebaseAnalytics.swift; sourceTree = ""; }; BE28092D1E8029D8006E50D5 /* AnalyticsConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyticsConfiguration.swift; sourceTree = ""; }; BE28092F1E8038BE006E50D5 /* ContentTabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTabBarViewController.swift; sourceTree = ""; }; BE4C21EA1E81970A00645143 /* DebugMenuConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugMenuConfiguration.swift; sourceTree = ""; }; @@ -546,7 +547,6 @@ 00551421206144E200E4CF68 /* InfoPlist.strings */, ABC778811DC90B7A00815FB9 /* LaunchScreen.storyboard */, ABF84F801DC97653002DB24D /* Localizable.strings */, - BE2809251E802474006E50D5 /* PRODUCTNAME-Bridging-Header.h */, ); path = Resources; sourceTree = ""; @@ -576,6 +576,7 @@ children = ( BE2809261E802893006E50D5 /* Analytics */, BE28092D1E8029D8006E50D5 /* AnalyticsConfiguration.swift */, + 280520552371F60E003E1041 /* AppCenterConfiguration.swift */, ABC778E01DC94F4400815FB9 /* AppLifecycle.swift */, ABC778E51DC94FFC00815FB9 /* CrashlyticsConfiguration.swift */, BE4C21EA1E81970A00645143 /* DebugMenuConfiguration.swift */, @@ -632,7 +633,7 @@ children = ( BE2809271E802893006E50D5 /* Analytics.swift */, BE2809281E802893006E50D5 /* AnalyticsPageNames.swift */, - BE2809291E802893006E50D5 /* GoogleAnalytics.swift */, + BE2809291E802893006E50D5 /* FirebaseAnalytics.swift */, ); path = Analytics; sourceTree = ""; @@ -703,6 +704,7 @@ ABC778BD1DC924EF00815FB9 /* Embed Frameworks */, 4B79AD4EE86D9527DA2201EB /* [CP] Embed Pods Frameworks */, 006EFEFF1F27B3C0004A95DE /* Crashlytics */, + E1B38BEC3F6162E864695F4C /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -723,6 +725,7 @@ ABC778861DC90B7A00815FB9 /* Frameworks */, ABC778871DC90B7A00815FB9 /* Resources */, 4E662DA2F7DDCC9B41361541 /* [CP] Embed Pods Frameworks */, + E61364E507C43F52B6FB7F4B /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -915,22 +918,26 @@ "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework", "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${PODS_ROOT}/Instabug/Instabug.framework", - "${PODS_ROOT}/Instabug/Instabug.framework.dSYM", "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework", + "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework", "${BUILT_PRODUCTS_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework", "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework", + "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Anchorage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BonMot.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Instabug.framework", - "${DWARF_DSYM_FOLDER_PATH}/Instabug.framework.dSYM", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KeychainAccess.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SimulatorStatusMagic.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Swiftilities.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -947,11 +954,13 @@ "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework", "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${PODS_ROOT}/Instabug/Instabug.framework", - "${PODS_ROOT}/Instabug/Instabug.framework.dSYM", "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework", + "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework", "${BUILT_PRODUCTS_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework", "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework", + "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", "${BUILT_PRODUCTS_DIR}/OHHTTPStubs/OHHTTPStubs.framework", ); name = "[CP] Embed Pods Frameworks"; @@ -959,11 +968,13 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Anchorage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BonMot.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Instabug.framework", - "${DWARF_DSYM_FOLDER_PATH}/Instabug.framework.dSYM", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KeychainAccess.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SimulatorStatusMagic.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Swiftilities.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OHHTTPStubs.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -1039,6 +1050,42 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + E1B38BEC3F6162E864695F4C /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/AppCenter/AppCenterDistributeResources.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AppCenterDistributeResources.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + E61364E507C43F52B6FB7F4B /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/AppCenter/AppCenterDistributeResources.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AppCenterDistributeResources.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1087,7 +1134,7 @@ 861732F81FA2989100C14354 /* TableViewContainerCell.swift in Sources */, CD09C94D207428AE006D3501 /* StatusBarConfiguration.swift in Sources */, 861732F51FA2984600C14354 /* TableViewCellRepresentable.swift in Sources */, - BE28092C1E802893006E50D5 /* GoogleAnalytics.swift in Sources */, + BE28092C1E802893006E50D5 /* FirebaseAnalytics.swift in Sources */, ABC778E11DC94F4400815FB9 /* AppLifecycle.swift in Sources */, 2DFF1D161E8BF38F00B1AD70 /* UIColor+Extensions.swift in Sources */, ABF84F921DC99D33002DB24D /* UIImage+Asset.swift in Sources */, @@ -1113,6 +1160,7 @@ 86A65B201FA0F6DB00705C14 /* UserDefaults+Utilities.swift in Sources */, 861732FE1FA29BE600C14354 /* DebugMenuViewController.swift in Sources */, 2DFF1D181E8BF82A00B1AD70 /* Color.swift in Sources */, + 280520562371F60E003E1041 /* AppCenterConfiguration.swift in Sources */, 861732D51FA28DB600C14354 /* ModalDismissBehavior.swift in Sources */, BE28092A1E802893006E50D5 /* Analytics.swift in Sources */, 2DFF1D121E8BE27B00B1AD70 /* OnboardingPageViewController.swift in Sources */, @@ -1240,7 +1288,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_MODULE_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "${PROVISIONING_PROFILE_PRODUCTNAME}"; - SWIFT_OBJC_BRIDGING_HEADER = "PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = AppStore; @@ -1608,7 +1655,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_MODULE_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "${PROVISIONING_PROFILE_PRODUCTNAME}"; - SWIFT_OBJC_BRIDGING_HEADER = "PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Debug; @@ -1623,7 +1669,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_MODULE_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "${PROVISIONING_PROFILE_PRODUCTNAME}"; - SWIFT_OBJC_BRIDGING_HEADER = "PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Develop; @@ -1722,7 +1767,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_MODULE_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "${PROVISIONING_PROFILE_PRODUCTNAME}"; - SWIFT_OBJC_BRIDGING_HEADER = "PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Sprint; diff --git a/PRODUCTNAME/app/PRODUCTNAME/Application/AppDelegate.swift b/PRODUCTNAME/app/PRODUCTNAME/Application/AppDelegate.swift index 4bfba05..20dd172 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Application/AppDelegate.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Application/AppDelegate.swift @@ -7,6 +7,10 @@ // import UIKit +#if canImport(AppCenter) +import AppCenter +import AppCenterDistribute +#endif @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -23,6 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { AnalyticsConfiguration(), DebugMenuConfiguration(), StatusBarConfiguration(), + AppCenterConfiguration(), ] // Anything that relies on the existence of a window and an initial viewcontroller should be in this postWindowConfigurations array @@ -53,4 +58,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } + func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { + #if canImport(AppCenter) + return MSDistribute.open(url) + #else + return false + #endif + } } diff --git a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/Analytics/FirebaseAnalytics.swift b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/Analytics/FirebaseAnalytics.swift new file mode 100644 index 0000000..0740438 --- /dev/null +++ b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/Analytics/FirebaseAnalytics.swift @@ -0,0 +1,66 @@ +// +// FirebaseAnalytics.swift +// PRODUCTNAME +// +// Created by LEADDEVELOPER on TODAYSDATE. +// Copyright © THISYEAR ORGANIZATION. All rights reserved. +// + +import Foundation +import Firebase +import Swiftilities +import Services + +class FirebaseAnalytics { + + static let shared: FirebaseAnalytics = { () -> FirebaseAnalytics in + let sh = FirebaseAnalytics() + sh.configure() + return sh + }() + + fileprivate func configure() { + if FirebaseApp.app() == nil { + FirebaseApp.configure() + } + } +} + +extension FirebaseAnalytics { + func configureApplication(_ application: UIApplication, launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + var filePath: String? + switch BuildType.active { + case .debug: + filePath = Bundle.main.path(forResource: "GoogleService-Info-Debug", ofType: "plist") + case .internal: + filePath = Bundle.main.path(forResource: "GoogleService-Info-Develop", ofType: "plist") + case .release: + filePath = Bundle.main.path(forResource: "GoogleService-Info-AppStore", ofType: "plist") + } + guard let path = filePath, + let options = FirebaseOptions(contentsOfFile: path) else { + Log.error("Firebase configuration not found!") + return false + } + FirebaseApp.configure(options: options) + return true + } +} + +extension FirebaseAnalytics: AnalyticsService { + + func trackPageView(page: String) { + print("Page sent to firebase: " + page) + Analytics.setScreenName(page, screenClass: page) + } + +} + +public class FirebaseTrackPageViewBehavior: ViewControllerLifecycleBehavior { + + public init() {} + public func afterAppearing(_ viewController: UIViewController, animated: Bool) { + FirebaseAnalytics.shared.track(viewController) + } +} diff --git a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/Analytics/GoogleAnalytics.swift b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/Analytics/GoogleAnalytics.swift deleted file mode 100644 index 9dc83ff..0000000 --- a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/Analytics/GoogleAnalytics.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// GoogleAnalytics.swift -// PRODUCTNAME -// -// Created by LEADDEVELOPER on TODAYSDATE. -// Copyright © THISYEAR ORGANIZATION. All rights reserved. -// - -import Foundation -import Swiftilities - -class GoogleAnalytics { - - private static let analyticsDictKey = "GoogleAnalytics" - private static let trackingId = "TrackingID" - private static let environment = "Environment" - private static let environmentCustomDimensionIndex: UInt = 1 - static let shared: GoogleAnalytics = { () -> GoogleAnalytics in - let sh = GoogleAnalytics() - sh.configure() - return sh - }() - - var tracker: GAITracker { - return GAI.sharedInstance().defaultTracker - } - - fileprivate func configure() { - if let gai = GAI.sharedInstance(), - let analyticsDict = Bundle.main.object(forInfoDictionaryKey: GoogleAnalytics.analyticsDictKey) as? [String: String], - let trackingId = analyticsDict[GoogleAnalytics.trackingId], - let environment = analyticsDict[GoogleAnalytics.environment] { - gai.trackUncaughtExceptions = false - gai.tracker(withTrackingId: trackingId) - // Set the value for the GA custom dimension representing the environment - either dev or prod - let environmentDimensionParameter = GAIFields.customDimension(for: GoogleAnalytics.environmentCustomDimensionIndex) - gai.defaultTracker.set(environmentDimensionParameter, value: environment) - - // Uncomment to manually verify analytic events. - // gai.logger.logLevel = GAILogLevel.verbose - gai.dryRun = true - } else { - preconditionFailure("Google Analytics configuration issue. Please ensure info.plist contains [\"GoogleAnalytics\":\"[\"Environment\":\"$(GA_ENVIRONMENT)\",\"TrackingID\":\"$(GA_TRACKING_ID)\"]] and either add GA_ENVIRONMENT and GA_TRACKING_ID to your xcconfig or hardcode them instead of the $() vars.") - } - } -} - -extension GoogleAnalytics: AnalyticsService { - - func trackPageView(page: String) { - tracker.set(kGAIScreenName, value: page) - if let builder = GAIDictionaryBuilder.createScreenView() { - tracker.send(builder.build() as [NSObject: AnyObject]) - } - } - -} - -public class GoogleTrackPageViewBehavior: ViewControllerLifecycleBehavior { - - public init() {} - public func afterAppearing(_ viewController: UIViewController, animated: Bool) { - GoogleAnalytics.shared.track(viewController) - } - -} diff --git a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AnalyticsConfiguration.swift b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AnalyticsConfiguration.swift index 1aa2b2c..8a4b4b5 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AnalyticsConfiguration.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AnalyticsConfiguration.swift @@ -7,6 +7,7 @@ // import Swiftilities +import Services import UIKit struct AnalyticsConfiguration: AppLifecycle, PageNameConfiguration { @@ -24,6 +25,18 @@ struct AnalyticsConfiguration: AppLifecycle, PageNameConfiguration { } func onDidLaunch(application: UIApplication, launchOptions: [UIApplication.LaunchOptionsKey: Any]?) { - DefaultBehaviors(behaviors: [GoogleTrackPageViewBehavior()]).inject() + + guard FirebaseAnalytics.shared.configureApplication(application, launchOptions: launchOptions) else { return } + + var behaviors: [ViewControllerLifecycleBehavior] = [] + switch BuildType.active { + case .release: + behaviors = [ + FirebaseTrackPageViewBehavior(), + ] + default: break + } + + DefaultBehaviors(behaviors: behaviors).inject() } } diff --git a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AppCenterConfiguration.swift b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AppCenterConfiguration.swift new file mode 100644 index 0000000..dfe0982 --- /dev/null +++ b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/AppCenterConfiguration.swift @@ -0,0 +1,24 @@ +// +// AppCenterConfiguration.swift +// PRODUCTNAME +// +// Created by Eliot Williams on 11/5/19. +// Copyright © 2019 ORGANIZATION. All rights reserved. +// + +import UIKit +#if canImport(AppCenter) +import AppCenter +import AppCenterDistribute +#endif + +struct AppCenterConfiguration: AppLifecycle { + func onDidLaunch(application: UIApplication, launchOptions: [UIApplication.LaunchOptionsKey: Any]?) { + #if canImport(AppCenter) + guard let appSecret = Bundle.main.object(forInfoDictionaryKey: "AppCenterAppSecret") as? String else { + return + } + MSAppCenter.start(appSecret, withServices: [MSDistribute.self]) + #endif + } +} diff --git a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/StatusBarConfiguration.swift b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/StatusBarConfiguration.swift index daab53a..2f00575 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/StatusBarConfiguration.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Application/AppLifecycle/StatusBarConfiguration.swift @@ -6,6 +6,8 @@ // Copyright © THISYEAR ORGANIZATION. All rights reserved. // +import UIKit + #if targetEnvironment(simulator) && DEBUG import SimulatorStatusMagic #endif diff --git a/PRODUCTNAME/app/PRODUCTNAME/Components/Protocols/Actionable.swift b/PRODUCTNAME/app/PRODUCTNAME/Components/Protocols/Actionable.swift index 38bd506..0574e06 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Components/Protocols/Actionable.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Components/Protocols/Actionable.swift @@ -6,6 +6,8 @@ // Copyright © THISYEAR ORGANIZATION. All rights reserved. // +import UIKit + protocol Actionable: class { associatedtype ActionType associatedtype Delegate diff --git a/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/SimpleTableCellItem.swift b/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/SimpleTableCellItem.swift index 243f15d..149e370 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/SimpleTableCellItem.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/SimpleTableCellItem.swift @@ -7,6 +7,7 @@ // import Foundation +import UIKit public struct SimpleTableCellItem { public typealias VoidBlock = () -> Void diff --git a/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/ViewRepresentable.swift b/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/ViewRepresentable.swift index 9d8778c..9436ba8 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/ViewRepresentable.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Components/Representable/ViewRepresentable.swift @@ -6,6 +6,8 @@ // Copyright © THISYEAR ORGANIZATION. All rights reserved. // +import UIKit + public protocol ViewRepresentable: AnyViewRepresentable { associatedtype View: UIView func makeView() -> View diff --git a/PRODUCTNAME/app/PRODUCTNAME/Components/Views/ControlContainable.swift b/PRODUCTNAME/app/PRODUCTNAME/Components/Views/ControlContainable.swift index c77bf60..6725235 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Components/Views/ControlContainable.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Components/Views/ControlContainable.swift @@ -7,6 +7,7 @@ // import Foundation +import UIKit final class ControlContainableScrollView: UIScrollView { diff --git a/PRODUCTNAME/app/PRODUCTNAME/Resources/Color.swift b/PRODUCTNAME/app/PRODUCTNAME/Resources/Color.swift index bf5e264..583b12f 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Resources/Color.swift +++ b/PRODUCTNAME/app/PRODUCTNAME/Resources/Color.swift @@ -6,6 +6,8 @@ // Copyright © THISYEAR ORGANIZATION. All rights reserved. // +import UIKit + enum Color { static let lightGray = UIColor.with(red: 170, green: 170, blue: 170) diff --git a/PRODUCTNAME/app/PRODUCTNAME/Resources/Info.plist b/PRODUCTNAME/app/PRODUCTNAME/Resources/Info.plist index f33a1ec..6907b35 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Resources/Info.plist +++ b/PRODUCTNAME/app/PRODUCTNAME/Resources/Info.plist @@ -2,6 +2,10 @@ + AppCenterAppDelegateForwarderEnabled + + AppCenterAppSecret + $(APPCENTER_APP_SECRET) CFBundleDevelopmentRegion en CFBundleExecutable diff --git a/PRODUCTNAME/app/PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h b/PRODUCTNAME/app/PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h deleted file mode 100644 index 44b0fda..0000000 --- a/PRODUCTNAME/app/PRODUCTNAME/Resources/PRODUCTNAME-Bridging-Header.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// PRODUCTNAME-Bridging-Header.h -// PRODUCTNAME -// -// Created by LEADDEVELOPER on TODAYSDATE. -// Copyright © THISYEAR ORGANIZATION. All rights reserved. -// - -// EXTERNAL - -#import -#import -#import - diff --git a/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Develop.xcconfig b/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Develop.xcconfig index 0e00c08..a9ebc05 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Develop.xcconfig +++ b/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Develop.xcconfig @@ -24,5 +24,8 @@ FABRIC_API_KEY = $(INTERNAL_FABRIC_API_KEY) FABRIC_BUILD_SECRET = $(INTERNAL_BUILD_SECRET) SWIFT_ACTIVE_COMPILATION_CONDITIONS = RZINTERNAL +//FIXME: Insert AppCenter Secret +// APPCENTER_APP_SECRET = xxxxxx + // This file must be included last to properly resolve the offical Xcode variables. #include "PRODUCTNAME/Resources/xcconfig/Global.xcconfig" diff --git a/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Sprint.xcconfig b/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Sprint.xcconfig index 871942a..7df07e9 100644 --- a/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Sprint.xcconfig +++ b/PRODUCTNAME/app/PRODUCTNAME/Resources/xcconfig/Sprint.xcconfig @@ -24,5 +24,8 @@ FABRIC_API_KEY = $(INTERNAL_FABRIC_API_KEY) FABRIC_BUILD_SECRET = $(INTERNAL_BUILD_SECRET) SWIFT_ACTIVE_COMPILATION_CONDITIONS = RZINTERNAL +//FIXME: Insert AppCenter Secret +// APPCENTER_APP_SECRET = xxxxxx + // This file must be included last to properly resolve the offical Xcode variables. #include "PRODUCTNAME/Resources/xcconfig/Global.xcconfig" diff --git a/PRODUCTNAME/app/Podfile b/PRODUCTNAME/app/Podfile index 6a5a5d1..1122b14 100644 --- a/PRODUCTNAME/app/Podfile +++ b/PRODUCTNAME/app/Podfile @@ -11,16 +11,23 @@ def shared pod 'Swiftilities' end +def firebase + pod 'Firebase/Core', :modular_headers => true + pod 'Firebase/Messaging', :modular_headers => true +end + target 'PRODUCTNAME' do pod 'Instabug' pod 'Crashlytics' - pod 'GoogleAnalytics', '~>3.0' + pod 'AppCenter/Distribute', :configurations => ['Sprint', 'Develop'] + firebase() pod 'SimulatorStatusMagic', :configurations => ['Debug'] target 'PRODUCTNAMETests' do pod 'OHHTTPStubs/Swift' + firebase() end shared() diff --git a/PRODUCTNAME/app/Podfile.lock b/PRODUCTNAME/app/Podfile.lock index cd52ee6..491ed15 100644 --- a/PRODUCTNAME/app/Podfile.lock +++ b/PRODUCTNAME/app/Podfile.lock @@ -1,13 +1,78 @@ PODS: - Alamofire (4.8.2) - Anchorage (4.3) + - AppCenter/Core (2.0.1) + - AppCenter/Distribute (2.0.1): + - AppCenter/Core - BonMot (5.3) - Crashlytics (3.12.0): - Fabric (~> 1.9.0) - Fabric (1.9.0) - - GoogleAnalytics (3.17.0) + - Firebase/Core (6.0.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.0.0) + - Firebase/CoreOnly (6.0.0): + - FirebaseCore (= 6.0.0) + - Firebase/Messaging (6.0.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 4.0.0) + - FirebaseAnalytics (6.0.0): + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleAppMeasurement (= 6.0.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - FirebaseAnalyticsInterop (1.2.0) + - FirebaseCore (6.0.0): + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Logger (~> 6.0) + - FirebaseInstanceID (4.0.0): + - FirebaseCore (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - FirebaseMessaging (4.0.0): + - FirebaseAnalyticsInterop (~> 1.1) + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Reachability (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - Protobuf (~> 3.1) + - GoogleAppMeasurement (6.0.0): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - GoogleUtilities/AppDelegateSwizzler (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.0.0) + - GoogleUtilities/Logger (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.0.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.0.0)" + - GoogleUtilities/Reachability (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.0.0): + - GoogleUtilities/Logger - Instabug (8.3) - KeychainAccess (3.2.0) + - nanopb (0.3.901): + - nanopb/decode (= 0.3.901) + - nanopb/encode (= 0.3.901) + - nanopb/decode (0.3.901) + - nanopb/encode (0.3.901) - OHHTTPStubs/Core (8.0.0) - OHHTTPStubs/Default (8.0.0): - OHHTTPStubs/Core @@ -21,6 +86,7 @@ PODS: - OHHTTPStubs/OHPathHelpers (8.0.0) - OHHTTPStubs/Swift (8.0.0): - OHHTTPStubs/Default + - Protobuf (3.7.0) - SimulatorStatusMagic (2.4.1) - Sourcery (0.16.1) - SwiftGen (6.1.0) @@ -89,9 +155,11 @@ PODS: DEPENDENCIES: - Alamofire - Anchorage + - AppCenter/Distribute - BonMot - Crashlytics - - GoogleAnalytics (~> 3.0) + - Firebase/Core + - Firebase/Messaging - Instabug - KeychainAccess - OHHTTPStubs/Swift @@ -105,13 +173,23 @@ SPEC REPOS: https://github.com/cocoapods/specs.git: - Alamofire - Anchorage + - AppCenter - BonMot - Crashlytics - Fabric - - GoogleAnalytics + - Firebase + - FirebaseAnalytics + - FirebaseAnalyticsInterop + - FirebaseCore + - FirebaseInstanceID + - FirebaseMessaging + - GoogleAppMeasurement + - GoogleUtilities - Instabug - KeychainAccess + - nanopb - OHHTTPStubs + - Protobuf - SimulatorStatusMagic - Sourcery - SwiftGen @@ -121,19 +199,29 @@ SPEC REPOS: SPEC CHECKSUMS: Alamofire: ae5c501addb7afdbb13687d7f2f722c78734c2d3 Anchorage: 21a98675245188427f0bcea21404d42a824a766f + AppCenter: 6a5ff2fd007b53431259fdd74f91eb3d0dfea3d1 BonMot: 0104d1b4eda54f4a4b7393d6559539ef25498fbd Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 Fabric: f988e33c97f08930a413e08123064d2e5f68d655 - GoogleAnalytics: f42cc53a87a51fe94334821868d9c8481ff47a7b + Firebase: fa80b9d987ca014a1ba9357496ef2a0178b28b12 + FirebaseAnalytics: 1743c5f4de3687d0745709dfdc4b1dea1484f44c + FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1 + FirebaseCore: e38f025287b413255a53acc1945d048a112047f7 + FirebaseInstanceID: 0e0348a3c00a734fa376a070f5ad4533ad975cb5 + FirebaseMessaging: c796d50864dc822a3c06c9c1c1444b37732b795b + GoogleAppMeasurement: 7f028ea162b72c8f326daec74afc95d94f7a47d6 + GoogleUtilities: f1faafc033ea203adf1783ce00af455bb99d0e5b Instabug: c61ac1b653b64596c1bd00cf5ba039f05aecb930 KeychainAccess: 3b1bf8a77eb4c6ea1ce9404c292e48f948954c6b + nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48 OHHTTPStubs: 9cbce6364bec557cc3439aa6bb7514670d780881 + Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a SimulatorStatusMagic: 28d4a9d1a500ac7cea0b2b5a43c1c6ddb40ba56c Sourcery: 16779170d35ee204666843b09031f36721a84bcc SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0 Swiftilities: 7b57b06b46df20236a1cd9faf64ab3fd7554f4ed SwiftLint: 009a898ef2a1c851f45e1b59349bf6ff2ddc990d -PODFILE CHECKSUM: f3cf654d6eed8a1c230b93a6ffde151bbf9179a5 +PODFILE CHECKSUM: f4deff92cb777959f68cae8d4fd0677ec3f2443f -COCOAPODS: 1.6.1 +COCOAPODS: 1.7.5 diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/AppCenter b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/AppCenter new file mode 100644 index 0000000..2b390cd Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/AppCenter differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/AppCenter.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/AppCenter.h new file mode 100644 index 0000000..d26bd4d --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/AppCenter.h @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSAbstractLog.h" +#import "MSAppCenter.h" +#import "MSAppCenterErrors.h" +#import "MSChannelGroupProtocol.h" +#import "MSChannelProtocol.h" +#import "MSConstants.h" +#import "MSCustomProperties.h" +#import "MSDevice.h" +#import "MSEnable.h" +#import "MSLog.h" +#import "MSLogWithProperties.h" +#import "MSLogger.h" +#import "MSService.h" +#import "MSServiceAbstract.h" +#import "MSUserInformation.h" +#import "MSWrapperLogger.h" +#import "MSWrapperSdk.h" diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAbstractLog.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAbstractLog.h new file mode 100644 index 0000000..e90b7ff --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAbstractLog.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@interface MSAbstractLog : NSObject + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenter.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenter.h new file mode 100644 index 0000000..39fd792 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenter.h @@ -0,0 +1,216 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSConstants.h" + +@class MSWrapperSdk; + +#if !TARGET_OS_TV +@class MSCustomProperties; +#endif + +@interface MSAppCenter : NSObject + +/** + * Returns the singleton instance of MSAppCenter. + */ ++ (instancetype)sharedInstance; + +/** + * Configure the SDK with an application secret. + * + * @param appSecret A unique and secret key used to identify the application. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)configureWithAppSecret:(NSString *)appSecret; + +/** + * Configure the SDK. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)configure; + +/** + * Configure the SDK with an application secret and an array of services to start. + * + * @param appSecret A unique and secret key used to identify the application. + * @param services Array of services to start. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)start:(NSString *)appSecret withServices:(NSArray *)services; + +/** + * Start the SDK with an array of services. + * + * @param services Array of services to start. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)startWithServices:(NSArray *)services; + +/** + * Start a service. + * + * @param service A service to start. + * + * @discussion This may be called only once per service per application process lifetime. + */ ++ (void)startService:(Class)service; + +/** + * Configure the SDK with an array of services to start from a library. This will not start the service at application level, it will enable + * the service only for the library. + * + * @param services Array of services to start. + */ ++ (void)startFromLibraryWithServices:(NSArray *)services; + +/** + * Check whether the SDK has already been configured or not. + * + * @return YES if configured, NO otherwise. + */ ++ (BOOL)isConfigured; + +/** + * Change the base URL (schema + authority + port only) used to communicate with the backend. + * + * @param logUrl Base URL to use for backend communication. + */ ++ (void)setLogUrl:(NSString *)logUrl; + +/** + * Enable or disable the SDK as a whole. In addition to AppCenter resources, it will also enable or disable all registered services. + * The state is persisted in the device's storage across application launches. + * + * @param isEnabled YES to enable, NO to disable. + * + * @see isEnabled + */ ++ (void)setEnabled:(BOOL)isEnabled; + +/** + * Check whether the SDK is enabled or not as a whole. + * + * @return YES if enabled, NO otherwise. + * + * @see setEnabled: + */ ++ (BOOL)isEnabled; + +/** + * Get log level. + * + * @return Log level. + */ ++ (MSLogLevel)logLevel; + +/** + * Set log level. + * + * @param logLevel The log level. + */ ++ (void)setLogLevel:(MSLogLevel)logLevel; + +/** + * Set log level handler. + * + * @param logHandler Handler. + */ ++ (void)setLogHandler:(MSLogHandler)logHandler; + +/** + * Set wrapper SDK information to use when building device properties. This is intended in case you are building a SDK that uses the App + * Center SDK under the hood, e.g. our Xamarin SDK or ReactNative SDk. + * + * @param wrapperSdk Wrapper SDK information. + */ ++ (void)setWrapperSdk:(MSWrapperSdk *)wrapperSdk; + +#if !TARGET_OS_TV +/** + * Set the custom properties. + * + * @param customProperties Custom properties object. + */ ++ (void)setCustomProperties:(MSCustomProperties *)customProperties; +#endif + +/** + * Check whether the application delegate forwarder is enabled or not. + * + * @return YES if enabled, NO otherwise. + * + * @discussion The application delegate forwarder forwards messages that target your application delegate methods via swizzling to the SDK. + * It simplifies the SDK integration but may not be suitable to any situations. For + * instance it should be disabled if you or one of your third party SDK is doing message forwarding on the application delegate. Message + * forwarding usually implies the implementation of @see NSObject#forwardingTargetForSelector: or @see NSObject#forwardInvocation: methods. + * To disable the application delegate forwarder just add the `AppCenterAppDelegateForwarderEnabled` tag to your Info .plist file and set it + * to `0`. Then you will have to forward any application delegate needed by the SDK manually. + */ ++ (BOOL)isAppDelegateForwarderEnabled; + +/** + * Get unique installation identifier. + * + * @return Unique installation identifier. + */ ++ (NSUUID *)installId; + +/** + * Detect if a debugger is attached to the app process. This is only invoked once on app startup and can not detect + * if the debugger is being attached during runtime! + * + * @return BOOL if the debugger is attached. + */ ++ (BOOL)isDebuggerAttached; + +/** + * Get the current version of AppCenter SDK. + * + * @return The current version of AppCenter SDK. + */ ++ (NSString *)sdkVersion; + +/** + * Set the maximum size of the internal storage. This method must be called before App Center is started. This method is only intended for + * applications. + * + * @param sizeInBytes Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size + * (default is 4096 bytes). Values below 20,480 bytes (20 KiB) will be ignored. + * + * @param completionHandler Callback that is invoked when the database size has been set. The `BOOL` parameter is `YES` if changing the size + * is successful, and `NO` otherwise. This parameter can be null. + * + * @discussion This only sets the maximum size of the database, but App Center modules might store additional data. + * The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + */ ++ (void)setMaxStorageSize:(long)sizeInBytes completionHandler:(void (^)(BOOL))completionHandler; + +/** + * Set the user identifier. + * + * @param userId User identifier. + * + * @discussion Set the user identifier for logs sent for the default target token when the secret passed in @c + * MSAppCenter:start:withServices: contains "target={targetToken}". + * + * For App Center backend the user identifier maximum length is 256 characters. + * + * AppCenter must be configured or started before this API can be used. + */ ++ (void)setUserId:(NSString *)userId; + +/** + * Set country code to use when building device properties. + * + * @param countryCode The two-letter ISO country code. @see https://www.iso.org/obp/ui/#search for more information. + */ ++ (void)setCountryCode:(NSString *)countryCode; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenterErrors.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenterErrors.h new file mode 100644 index 0000000..a29c7aa --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenterErrors.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#define MS_APP_CENTER_BASE_DOMAIN @"com.Microsoft.AppCenter." + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Domain + +static NSString *const kMSACErrorDomain = MS_APP_CENTER_BASE_DOMAIN @"ErrorDomain"; + +#pragma mark - General + +// Error codes. +NS_ENUM(NSInteger){MSACLogInvalidContainerErrorCode = 1, MSACCanceledErrorCode = 2, MSACDisabledErrorCode = 3}; + +// Error descriptions. +static NSString const *kMSACLogInvalidContainerErrorDesc = @"Invalid log container."; +static NSString const *kMSACCanceledErrorDesc = @"The operation was canceled."; +static NSString const *kMSACDisabledErrorDesc = @"The service is disabled."; + +#pragma mark - Connection + +// Error codes. +NS_ENUM(NSInteger){MSACConnectionPausedErrorCode = 100, MSACConnectionHttpErrorCode = 101}; + +// Error descriptions. +static NSString const *kMSACConnectionHttpErrorDesc = @"An HTTP error occured."; +static NSString const *kMSACConnectionPausedErrorDesc = @"Canceled, connection paused with log deletion."; + +// Error user info keys. +static NSString const *kMSACConnectionHttpCodeErrorKey = @"MSACConnectionHttpCode"; + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelGroupProtocol.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelGroupProtocol.h new file mode 100644 index 0000000..8b0aa95 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelGroupProtocol.h @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSChannelProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@class MSChannelUnitConfiguration; + +@protocol MSIngestionProtocol; +@protocol MSChannelUnitProtocol; + +/** + * `MSChannelGroupProtocol` represents a kind of channel that contains constituent MSChannelUnit objects. When an operation from the + * `MSChannelProtocol` is performed on the group, that operation should be propagated to its constituent MSChannelUnit objects. + */ +@protocol MSChannelGroupProtocol + +/** + * Initialize a channel unit with the given configuration. + * + * @param configuration channel configuration. + * + * @return The added `MSChannelUnitProtocol`. Use this object to enqueue logs. + */ +- (id)addChannelUnitWithConfiguration:(MSChannelUnitConfiguration *)configuration; + +/** + * Initialize a channel unit with the given configuration. + * + * @param configuration channel configuration. + * @param ingestion The alternative ingestion object + * + * @return The added `MSChannelUnitProtocol`. Use this object to enqueue logs. + */ +- (id)addChannelUnitWithConfiguration:(MSChannelUnitConfiguration *)configuration + withIngestion:(nullable id)ingestion; + +/** + * Change the base URL (schema + authority + port only) used to communicate with the backend. + * + * @param logUrl base URL to use for backend communication. + */ +- (void)setLogUrl:(NSString *)logUrl; + +/** + * Set the app secret. + * + * @param appSecret The app secret. + */ +- (void)setAppSecret:(NSString *)appSecret; + +/** + * Set the maximum size of the internal storage. This method must be called before App Center is started. + * + * @discussion The default maximum database size is 10485760 bytes (10 MiB). + * + * @param sizeInBytes Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size + * (default is 4096 bytes). Values below 24576 bytes (24 KiB) will be ignored. + * @param completionHandler Callback that is invoked when the database size has been set. The `BOOL` parameter is `YES` if changing the size + * is successful, and `NO` otherwise. + */ +- (void)setMaxStorageSize:(long)sizeInBytes completionHandler:(nullable void (^)(BOOL))completionHandler; + +/** + * Return a channel unit instance for the given groupId. + * + * @param groupId The group ID for a channel unit. + * + * @return A channel unit instance or `nil`. + */ +- (id)channelUnitForGroupId:(NSString *)groupId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelProtocol.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelProtocol.h new file mode 100644 index 0000000..5198b86 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelProtocol.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSEnable.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol MSChannelDelegate; + +/** + * `MSChannelProtocol` contains the essential operations of a channel. Channels are broadly responsible for enqueuing logs to be sent to the + * backend and/or stored on disk. + */ +@protocol MSChannelProtocol + +/** + * Add delegate. + * + * @param delegate delegate. + */ +- (void)addDelegate:(id)delegate; + +/** + * Remove delegate. + * + * @param delegate delegate. + */ +- (void)removeDelegate:(id)delegate; + +/** + * Pause operations, logs will be stored but not sent. + * + * @param identifyingObject Object used to identify the pause request. + * + * @discussion A paused channel doesn't forward logs to the ingestion. The identifying object used to pause the channel can be any unique + * object. The same identifying object must be used to call resume. For simplicity if the caller is the one owning the channel then @c self + * can be used as identifying object. + * + * @see resumeWithIdentifyingObject: + */ +- (void)pauseWithIdentifyingObject:(id)identifyingObject; + +/** + * Resume operations, logs can be sent again. + * + * @param identifyingObject Object used to passed to the pause method. + * + * @discussion The channel only resume when all the outstanding identifying objects have been resumed. + * + * @see pauseWithIdentifyingObject: + */ +- (void)resumeWithIdentifyingObject:(id)identifyingObject; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSConstants.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSConstants.h new file mode 100644 index 0000000..047c9f7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSConstants.h @@ -0,0 +1,170 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Log Levels + */ +typedef NS_ENUM(NSUInteger, MSLogLevel) { + + /** + * Logging will be very chatty + */ + MSLogLevelVerbose = 2, + + /** + * Debug information will be logged + */ + MSLogLevelDebug = 3, + + /** + * Information will be logged + */ + MSLogLevelInfo = 4, + + /** + * Errors and warnings will be logged + */ + MSLogLevelWarning = 5, + + /** + * Errors will be logged + */ + MSLogLevelError = 6, + + /** + * Only critical errors will be logged + */ + MSLogLevelAssert = 7, + + /** + * Logging is disabled + */ + MSLogLevelNone = 99 +}; + +typedef NSString * (^MSLogMessageProvider)(void); +typedef void (^MSLogHandler)(MSLogMessageProvider messageProvider, MSLogLevel logLevel, NSString *tag, const char *file, + const char *function, uint line); + +/** + * Channel priorities, check the kMSPriorityCount if you add a new value. + * The order matters here! Values NEED to range from low priority to high priority. + */ +typedef NS_ENUM(NSInteger, MSPriority) { MSPriorityBackground, MSPriorityDefault, MSPriorityHigh }; +static short const kMSPriorityCount = MSPriorityHigh + 1; + +/** + * The priority by which the modules are initialized. + * MSPriorityMax is reserved for only 1 module and this needs to be Crashes. + * Crashes needs to be initialized first to catch crashes in our other SDK Modules (which will hopefully never happen) and to avoid losing + * any log at crash time. + */ +typedef NS_ENUM(NSInteger, MSInitializationPriority) { + MSInitializationPriorityDefault = 500, + MSInitializationPriorityHigh = 750, + MSInitializationPriorityMax = 999 +}; + +/** + * Enum with the different HTTP status codes. + */ +typedef NS_ENUM(NSInteger, MSHTTPCodesNo) { + + // Invalid + MSHTTPCodesNo0XXInvalidUnknown = 0, + + // Informational + MSHTTPCodesNo1XXInformationalUnknown = 1, + MSHTTPCodesNo100Continue = 100, + MSHTTPCodesNo101SwitchingProtocols = 101, + MSHTTPCodesNo102Processing = 102, + + // Success + MSHTTPCodesNo2XXSuccessUnknown = 2, + MSHTTPCodesNo200OK = 200, + MSHTTPCodesNo201Created = 201, + MSHTTPCodesNo202Accepted = 202, + MSHTTPCodesNo203NonAuthoritativeInformation = 203, + MSHTTPCodesNo204NoContent = 204, + MSHTTPCodesNo205ResetContent = 205, + MSHTTPCodesNo206PartialContent = 206, + MSHTTPCodesNo207MultiStatus = 207, + MSHTTPCodesNo208AlreadyReported = 208, + MSHTTPCodesNo209IMUsed = 209, + + // Redirection + MSHTTPCodesNo3XXSuccessUnknown = 3, + MSHTTPCodesNo300MultipleChoices = 300, + MSHTTPCodesNo301MovedPermanently = 301, + MSHTTPCodesNo302Found = 302, + MSHTTPCodesNo303SeeOther = 303, + MSHTTPCodesNo304NotModified = 304, + MSHTTPCodesNo305UseProxy = 305, + MSHTTPCodesNo306SwitchProxy = 306, + MSHTTPCodesNo307TemporaryRedirect = 307, + MSHTTPCodesNo308PermanentRedirect = 308, + + // Client error + MSHTTPCodesNo4XXSuccessUnknown = 4, + MSHTTPCodesNo400BadRequest = 400, + MSHTTPCodesNo401Unauthorised = 401, + MSHTTPCodesNo402PaymentRequired = 402, + MSHTTPCodesNo403Forbidden = 403, + MSHTTPCodesNo404NotFound = 404, + MSHTTPCodesNo405MethodNotAllowed = 405, + MSHTTPCodesNo406NotAcceptable = 406, + MSHTTPCodesNo407ProxyAuthenticationRequired = 407, + MSHTTPCodesNo408RequestTimeout = 408, + MSHTTPCodesNo409Conflict = 409, + MSHTTPCodesNo410Gone = 410, + MSHTTPCodesNo411LengthRequired = 411, + MSHTTPCodesNo412PreconditionFailed = 412, + MSHTTPCodesNo413RequestEntityTooLarge = 413, + MSHTTPCodesNo414RequestURITooLong = 414, + MSHTTPCodesNo415UnsupportedMediaType = 415, + MSHTTPCodesNo416RequestedRangeNotSatisfiable = 416, + MSHTTPCodesNo417ExpectationFailed = 417, + MSHTTPCodesNo418IamATeapot = 418, + MSHTTPCodesNo419AuthenticationTimeout = 419, + MSHTTPCodesNo420MethodFailureSpringFramework = 420, + MSHTTPCodesNo420EnhanceYourCalmTwitter = 4200, + MSHTTPCodesNo422UnprocessableEntity = 422, + MSHTTPCodesNo423Locked = 423, + MSHTTPCodesNo424FailedDependency = 424, + MSHTTPCodesNo424MethodFailureWebDaw = 4240, + MSHTTPCodesNo425UnorderedCollection = 425, + MSHTTPCodesNo426UpgradeRequired = 426, + MSHTTPCodesNo428PreconditionRequired = 428, + MSHTTPCodesNo429TooManyRequests = 429, + MSHTTPCodesNo431RequestHeaderFieldsTooLarge = 431, + MSHTTPCodesNo444NoResponseNginx = 444, + MSHTTPCodesNo449RetryWithMicrosoft = 449, + MSHTTPCodesNo450BlockedByWindowsParentalControls = 450, + MSHTTPCodesNo451RedirectMicrosoft = 451, + MSHTTPCodesNo451UnavailableForLegalReasons = 4510, + MSHTTPCodesNo494RequestHeaderTooLargeNginx = 494, + MSHTTPCodesNo495CertErrorNginx = 495, + MSHTTPCodesNo496NoCertNginx = 496, + MSHTTPCodesNo497HTTPToHTTPSNginx = 497, + MSHTTPCodesNo499ClientClosedRequestNginx = 499, + + // Server error + MSHTTPCodesNo5XXSuccessUnknown = 5, + MSHTTPCodesNo500InternalServerError = 500, + MSHTTPCodesNo501NotImplemented = 501, + MSHTTPCodesNo502BadGateway = 502, + MSHTTPCodesNo503ServiceUnavailable = 503, + MSHTTPCodesNo504GatewayTimeout = 504, + MSHTTPCodesNo505HTTPVersionNotSupported = 505, + MSHTTPCodesNo506VariantAlsoNegotiates = 506, + MSHTTPCodesNo507InsufficientStorage = 507, + MSHTTPCodesNo508LoopDetected = 508, + MSHTTPCodesNo509BandwidthLimitExceeded = 509, + MSHTTPCodesNo510NotExtended = 510, + MSHTTPCodesNo511NetworkAuthenticationRequired = 511, + MSHTTPCodesNo522ConnectionTimedOut = 522, + MSHTTPCodesNo598NetworkReadTimeoutErrorUnknown = 598, + MSHTTPCodesNo599NetworkConnectTimeoutErrorUnknown = 599 +}; diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSCustomProperties.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSCustomProperties.h new file mode 100644 index 0000000..17e4a2a --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSCustomProperties.h @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Custom properties builder. + * Collects multiple properties to send in one log. + */ +@interface MSCustomProperties : NSObject + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setString:(NSString *)value forKey:(NSString *)key; + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setNumber:(NSNumber *)value forKey:(NSString *)key; + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setBool:(BOOL)value forKey:(NSString *)key; + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setDate:(NSDate *)value forKey:(NSString *)key; + +/** + * Clear the property for the specified key. + * + * @param key Key whose mapping is to be cleared. + * + * @return This instance. + */ +- (instancetype)clearPropertyForKey:(NSString *)key; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSDevice.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSDevice.h new file mode 100644 index 0000000..587a22a --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSDevice.h @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSWrapperSdk.h" + +@interface MSDevice : MSWrapperSdk + +/* + * Name of the SDK. Consists of the name of the SDK and the platform, e.g. "appcenter.ios", "appcenter.android" + */ +@property(nonatomic, copy, readonly) NSString *sdkName; + +/* + * Version of the SDK in semver format, e.g. "1.2.0" or "0.12.3-alpha.1". + */ +@property(nonatomic, copy, readonly) NSString *sdkVersion; + +/* + * Device model (example: iPad2,3). + */ +@property(nonatomic, copy, readonly) NSString *model; + +/* + * Device manufacturer (example: HTC). + */ +@property(nonatomic, copy, readonly) NSString *oemName; + +/* + * OS name (example: iOS). + */ +@property(nonatomic, copy, readonly) NSString *osName; + +/* + * OS version (example: 9.3.0). + */ +@property(nonatomic, copy, readonly) NSString *osVersion; + +/* + * OS build code (example: LMY47X). [optional] + */ +@property(nonatomic, copy, readonly) NSString *osBuild; + +/* + * API level when applicable like in Android (example: 15). [optional] + */ +@property(nonatomic, copy, readonly) NSNumber *osApiLevel; + +/* + * Language code (example: en_US). + */ +@property(nonatomic, copy, readonly) NSString *locale; + +/* + * The offset in minutes from UTC for the device time zone, including daylight savings time. + */ +@property(nonatomic, readonly) NSNumber *timeZoneOffset; + +/* + * Screen size of the device in pixels (example: 640x480). + */ +@property(nonatomic, copy, readonly) NSString *screenSize; + +/* + * Application version name, e.g. 1.1.0 + */ +@property(nonatomic, copy, readonly) NSString *appVersion; + +/* + * Carrier name (for mobile devices). [optional] + */ +@property(nonatomic, copy, readonly) NSString *carrierName; + +/* + * Carrier country code (for mobile devices). [optional] + */ +@property(nonatomic, copy, readonly) NSString *carrierCountry; + +/* + * The app's build number, e.g. 42. + */ +@property(nonatomic, copy, readonly) NSString *appBuild; + +/* + * The bundle identifier, package identifier, or namespace, depending on what the individual plattforms use, .e.g com.microsoft.example. + * [optional] + */ +@property(nonatomic, copy, readonly) NSString *appNamespace; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSEnable.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSEnable.h new file mode 100644 index 0000000..e092b1a --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSEnable.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Protocol to define an instance that can be enabled/disabled. + */ +@protocol MSEnable + +@required + +/** + * Enable/disable this instance and delete data on disabled state. + * + * @param isEnabled A boolean value set to YES to enable the instance or NO to disable it. + * @param deleteData A boolean value set to YES to delete data or NO to keep it. + */ +- (void)setEnabled:(BOOL)isEnabled andDeleteDataOnDisabled:(BOOL)deleteData; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLog.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLog.h new file mode 100644 index 0000000..d62aa62 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLog.h @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@class MSDevice; + +@protocol MSLog + +/** + * Log type. + */ +@property(nonatomic, copy) NSString *type; + +/** + * Log timestamp. + */ +@property(nonatomic) NSDate *timestamp; + +/** + * A session identifier is used to correlate logs together. A session is an abstract concept in the API and is not necessarily an analytics + * session, it can be used to only track crashes. + */ +@property(nonatomic, copy) NSString *sid; + +/** + * Optional distribution group ID value. + */ +@property(nonatomic, copy) NSString *distributionGroupId; + +/** + * Optional user identifier. + */ +@property(nonatomic, copy) NSString *userId; + +/** + * Device properties associated to this log. + */ +@property(nonatomic) MSDevice *device; + +/** + * Transient object tag. For example, a log can be tagged with a transmission target. We do this currently to prevent properties being + * applied retroactively to previous logs by comparing their tags. + */ +@property(nonatomic) NSObject *tag; + +/** + * Checks if the object's values are valid. + * + * @return YES, if the object is valid. + */ +- (BOOL)isValid; + +/** + * Adds a transmission target token that this log should be sent to. + * + * @param token The transmission target token. + */ +- (void)addTransmissionTargetToken:(NSString *)token; + +/** + * Gets all transmission target tokens that this log should be sent to. + * + * @returns Collection of transmission target tokens that this log should be sent to. + */ +- (NSSet *)transmissionTargetTokens; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogWithProperties.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogWithProperties.h new file mode 100644 index 0000000..f9fdd5c --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogWithProperties.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSAbstractLog.h" + +@interface MSLogWithProperties : MSAbstractLog + +/** + * Additional key/value pair parameters. [optional] + */ +@property(nonatomic) NSDictionary *properties; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogger.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogger.h new file mode 100644 index 0000000..7eb5c3b --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogger.h @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSConstants.h" + +#define MSLog(_level, _tag, _message) \ + [MSLogger logMessage:_message level:_level tag:_tag file:__FILE__ function:__PRETTY_FUNCTION__ line:__LINE__] +#define MSLogAssert(tag, format, ...) \ + MSLog(MSLogLevelAssert, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogError(tag, format, ...) \ + MSLog(MSLogLevelError, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogWarning(tag, format, ...) \ + MSLog(MSLogLevelWarning, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogInfo(tag, format, ...) \ + MSLog(MSLogLevelInfo, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogDebug(tag, format, ...) \ + MSLog(MSLogLevelDebug, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogVerbose(tag, format, ...) \ + MSLog(MSLogLevelVerbose, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) + +@interface MSLogger : NSObject + ++ (void)logMessage:(MSLogMessageProvider)messageProvider + level:(MSLogLevel)loglevel + tag:(NSString *)tag + file:(const char *)file + function:(const char *)function + line:(uint)line; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSService.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSService.h new file mode 100644 index 0000000..72c929d --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSService.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Protocol declaring service logic. + */ +@protocol MSService + +/** + * Enable or disable this service. + * The state is persisted in the device's storage across application launches. + * + * @param isEnabled Whether this service is enabled or not. + * + * @see isEnabled + */ ++ (void)setEnabled:(BOOL)isEnabled; + +/** + * Indicates whether this service is enabled. + * + * @return `YES` if this service is enabled, `NO` if it is not. + * + * @see setEnabled: + */ ++ (BOOL)isEnabled; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSServiceAbstract.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSServiceAbstract.h new file mode 100644 index 0000000..d51e1e1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSServiceAbstract.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSService.h" + +@protocol MSChannelGroupProtocol; + +/** + * Abstraction of services common logic. + * This class is intended to be subclassed only not instantiated directly. + */ +@interface MSServiceAbstract : NSObject + +/** + * The flag indicates whether the service is started from application or not. + */ +@property(nonatomic) BOOL startedFromApplication; + +/** + * Start this service with a channel group. Also sets the flag that indicates that a service has been started. + * + * @param channelGroup channel group used to persist and send logs. + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + * @param fromApplication indicates whether the service started from an application or not. + */ +- (void)startWithChannelGroup:(id)channelGroup + appSecret:(NSString *)appSecret + transmissionTargetToken:(NSString *)token + fromApplication:(BOOL)fromApplication; + +/** + * Update configuration when the service requires to start again. This method should only be called if the service is started from libraries + * and then is being started from an application. + * + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + */ +- (void)updateConfigurationWithAppSecret:(NSString *)appSecret transmissionTargetToken:(NSString *)token; + +/** + * Checks if the service needs the application secret. + * + * @return `YES` if the application secret is required, `NO` otherwise. + */ +- (BOOL)isAppSecretRequired; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSUserInformation.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSUserInformation.h new file mode 100644 index 0000000..8f8b7c6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSUserInformation.h @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MSUserInformation : NSObject + +/** + * The account identifier for the user. + */ +@property(nonatomic, copy) NSString *accountId; + +/** + * Create user with account identifier. + * + * @param accountId account identifier for the user. + * + * @return user with account identifier. + */ +- (instancetype)initWithAccountId:(NSString *)accountId; +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperLogger.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperLogger.h new file mode 100644 index 0000000..1e17ff1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperLogger.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSConstants.h" + +/** + * This is a utility for producing App Center style log messages. It is only intended for use by App Center services and wrapper SDKs of App + * Center. + */ +@interface MSWrapperLogger : NSObject + ++ (void)MSWrapperLog:(MSLogMessageProvider)message tag:(NSString *)tag level:(MSLogLevel)level; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperSdk.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperSdk.h new file mode 100644 index 0000000..29b5a58 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperSdk.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@interface MSWrapperSdk : NSObject + +/* + * Version of the wrapper SDK. When the SDK is embedding another base SDK (for example Xamarin.Android wraps Android), the Xamarin specific + * version is populated into this field while sdkVersion refers to the original Android SDK. [optional] + */ +@property(nonatomic, copy, readonly) NSString *wrapperSdkVersion; + +/* + * Name of the wrapper SDK (examples: Xamarin, Cordova). [optional] + */ +@property(nonatomic, copy, readonly) NSString *wrapperSdkName; + +/* + * Version of the wrapper technology framework (Xamarin runtime version or ReactNative or Cordova etc...). [optional] + */ +@property(nonatomic, copy, readonly) NSString *wrapperRuntimeVersion; + +/* + * Label that is used to identify application code 'version' released via Live Update beacon running on device. + */ +@property(nonatomic, copy, readonly) NSString *liveUpdateReleaseLabel; + +/* + * Identifier of environment that current application release belongs to, deployment key then maps to environment like Production, Staging. + */ +@property(nonatomic, copy, readonly) NSString *liveUpdateDeploymentKey; + +/* + * Hash of all files (ReactNative or Cordova) deployed to device via LiveUpdate beacon. Helps identify the Release version on device or need + * to download updates in future + */ +@property(nonatomic, copy, readonly) NSString *liveUpdatePackageHash; + +- (instancetype)initWithWrapperSdkVersion:(NSString *)wrapperSdkVersion + wrapperSdkName:(NSString *)wrapperSdkName + wrapperRuntimeVersion:(NSString *)wrapperRuntimeVersion + liveUpdateReleaseLabel:(NSString *)liveUpdateReleaseLabel + liveUpdateDeploymentKey:(NSString *)liveUpdateDeploymentKey + liveUpdatePackageHash:(NSString *)liveUpdatePackageHash; + +/** + * Checks if the object's values are valid. + * + * @return YES, if the object is valid. + */ +- (BOOL)isValid; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Modules/module.modulemap b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Modules/module.modulemap new file mode 100644 index 0000000..f15d734 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Modules/module.modulemap @@ -0,0 +1,13 @@ +framework module AppCenter { + umbrella header "AppCenter.h" + + export * + module * { export * } + + link framework "Foundation" + link framework "CoreTelephony" + link framework "SystemConfiguration" + link framework "UIKit" + link "sqlite3" + link "z" +} diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/AppCenterDistribute b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/AppCenterDistribute new file mode 100644 index 0000000..1c5934e Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/AppCenterDistribute differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/AppCenterDistribute.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/AppCenterDistribute.h new file mode 100644 index 0000000..8cf0eef --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/AppCenterDistribute.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSDistribute.h" +#import "MSDistributeDelegate.h" +#import "MSReleaseDetails.h" diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistribute.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistribute.h new file mode 100644 index 0000000..4b06f12 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistribute.h @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import "MSDistributeDelegate.h" +#import "MSServiceAbstract.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * App Center Distribute service. + */ +@interface MSDistribute : MSServiceAbstract + +/** + * Set a Distribute delegate + * + * @param delegate A Distribute delegate. + * + * @discussion If Distribute delegate is set and releaseAvailableWithDetails is returning YES, you must call + * notifyUpdateAction: with one of update actions to handle a release properly. + * + * @see releaseAvailableWithDetails: + * @see notifyUpdateAction: + */ ++ (void)setDelegate:(id)delegate; + +/** + * Notify SDK with an update action to handle the release. + */ ++ (void)notifyUpdateAction:(MSUpdateAction)action; + +/** + * Change The URL that will be used for generic update related tasks. + * + * @param apiUrl The new URL. + */ ++ (void)setApiUrl:(NSString *)apiUrl; + +/** + * Change the base URL that is used to install update. + * + * @param installUrl The new URL. + */ ++ (void)setInstallUrl:(NSString *)installUrl; + +/** + * Process URL request for the service. + * + * @param url The url with parameters. + * + * @return `YES` if the URL is intended for App Center Distribute and your application, `NO` otherwise. + * + * @discussion Place this method call into your app delegate's openURL method. + */ ++ (BOOL)openURL:(NSURL *)url; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistributeDelegate.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistributeDelegate.h new file mode 100644 index 0000000..f9c34c3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistributeDelegate.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import "MSReleaseDetails.h" + +@class MSDistribute; + +@protocol MSDistributeDelegate + +typedef NS_ENUM(NSInteger, MSUpdateAction) { + + /** + * Action to trigger update. + */ + MSUpdateActionUpdate, + + /** + * Action to postpone update. + */ + MSUpdateActionPostpone +}; + +@optional + +/** + * Callback method that will be called whenever a new release is available for update. + * + * @param distribute The instance of MSDistribute. + * @param details Release details for the update. + * + * @return Return YES if you want to take update control by overriding default update dialog, NO otherwise. + * + * @see [MSDistribute notifyUpdateAction:] + */ +- (BOOL)distribute:(MSDistribute *)distribute releaseAvailableWithDetails:(MSReleaseDetails *)details; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSReleaseDetails.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSReleaseDetails.h new file mode 100644 index 0000000..a5c1238 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSReleaseDetails.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@class MSDistributionGroup; + +/** + * Details of an uploaded release. + */ +@interface MSReleaseDetails : NSObject + +/** + * ID identifying this unique release. + */ +@property(nonatomic, copy) NSNumber *id; + +/** + * The release's version + * For iOS: CFBundleVersion from info.plist + * For Android: android:versionCode from AndroidManifest.xml + */ +@property(nonatomic, copy) NSString *version; + +/** + * The release's short version. + * For iOS: CFBundleShortVersionString from info.plist + * For Android: android:versionName from AndroidManifest.xml + */ +@property(nonatomic, copy) NSString *shortVersion; + +/** + * The release's release notes. + */ +@property(nonatomic, copy) NSString *releaseNotes; + +/** + * The flag that indicates whether the release is a mandatory update or not. + */ +@property(nonatomic) BOOL mandatoryUpdate; + +/** + * The URL that hosts the release notes for this release. + */ +@property(nonatomic) NSURL *releaseNotesUrl; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSService.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSService.h new file mode 100644 index 0000000..72c929d --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSService.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Protocol declaring service logic. + */ +@protocol MSService + +/** + * Enable or disable this service. + * The state is persisted in the device's storage across application launches. + * + * @param isEnabled Whether this service is enabled or not. + * + * @see isEnabled + */ ++ (void)setEnabled:(BOOL)isEnabled; + +/** + * Indicates whether this service is enabled. + * + * @return `YES` if this service is enabled, `NO` if it is not. + * + * @see setEnabled: + */ ++ (BOOL)isEnabled; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSServiceAbstract.h b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSServiceAbstract.h new file mode 100644 index 0000000..d51e1e1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSServiceAbstract.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSService.h" + +@protocol MSChannelGroupProtocol; + +/** + * Abstraction of services common logic. + * This class is intended to be subclassed only not instantiated directly. + */ +@interface MSServiceAbstract : NSObject + +/** + * The flag indicates whether the service is started from application or not. + */ +@property(nonatomic) BOOL startedFromApplication; + +/** + * Start this service with a channel group. Also sets the flag that indicates that a service has been started. + * + * @param channelGroup channel group used to persist and send logs. + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + * @param fromApplication indicates whether the service started from an application or not. + */ +- (void)startWithChannelGroup:(id)channelGroup + appSecret:(NSString *)appSecret + transmissionTargetToken:(NSString *)token + fromApplication:(BOOL)fromApplication; + +/** + * Update configuration when the service requires to start again. This method should only be called if the service is started from libraries + * and then is being started from an application. + * + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + */ +- (void)updateConfigurationWithAppSecret:(NSString *)appSecret transmissionTargetToken:(NSString *)token; + +/** + * Checks if the service needs the application secret. + * + * @return `YES` if the application secret is required, `NO` otherwise. + */ +- (BOOL)isAppSecretRequired; + +@end diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Modules/module.modulemap b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Modules/module.modulemap new file mode 100644 index 0000000..f89a286 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Modules/module.modulemap @@ -0,0 +1,10 @@ +framework module AppCenterDistribute { + umbrella header "AppCenterDistribute.h" + + export * + module * { export * } + + link framework "Foundation" + link framework "SafariServices" + link framework "UIKit" +} diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..2693e0b Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..bc7d18b Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..61329ba Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..a0c78ce Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..71db5ab Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..9a1461d Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..2eb663a Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..7d35e54 Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..04346ed Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..6341c8d Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..bfabe63 Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..767f8ea Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..4f88c85 Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj/AppCenterDistribute.strings b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..ff29885 Binary files /dev/null and b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj/AppCenterDistribute.strings differ diff --git a/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/LICENSE b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/LICENSE new file mode 100644 index 0000000..6a66415 --- /dev/null +++ b/PRODUCTNAME/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/LICENSE @@ -0,0 +1,25 @@ +Visual Studio App Center SDK for Apple platforms + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Firebase/CoreOnly/Sources/Firebase.h b/PRODUCTNAME/app/Pods/Firebase/CoreOnly/Sources/Firebase.h new file mode 100755 index 0000000..c9f033d --- /dev/null +++ b/PRODUCTNAME/app/Pods/Firebase/CoreOnly/Sources/Firebase.h @@ -0,0 +1,150 @@ +#import + +#if !defined(__has_include) + #error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \ + import the headers individually." +#else + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Dynamic Links works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase In App Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif +#endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Performance works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Remote Config works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + +#endif // defined(__has_include) diff --git a/PRODUCTNAME/app/Pods/Firebase/CoreOnly/Sources/module.modulemap b/PRODUCTNAME/app/Pods/Firebase/CoreOnly/Sources/module.modulemap new file mode 100755 index 0000000..3685b54 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Firebase/CoreOnly/Sources/module.modulemap @@ -0,0 +1,4 @@ +module Firebase { + export * + header "Firebase.h" +} \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Firebase/README.md b/PRODUCTNAME/app/Pods/Firebase/README.md new file mode 100755 index 0000000..20aa692 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Firebase/README.md @@ -0,0 +1,93 @@ +# Firebase APIs for iOS + +Simplify your iOS development, grow your user base, and monetize more +effectively with Firebase services. + +Much more information can be found at [https://firebase.google.com](https://firebase.google.com). + +## Install a Firebase SDK using CocoaPods + +Firebase distributes several iOS specific APIs and SDKs via CocoaPods. +You can install the CocoaPods tool on OS X by running the following command from +the terminal. Detailed information is available in the [Getting Started +guide](https://guides.cocoapods.org/using/getting-started.html#getting-started). + +``` +$ sudo gem install cocoapods +``` + +## Try out an SDK + +You can try any of the SDKs with `pod try`. Run the following command and select +the SDK you are interested in when prompted: + +``` +$ pod try Firebase +``` + +Note that some SDKs may require credentials. More information is available in +the SDK-specific documentation at [https://firebase.google.com/docs/](https://firebase.google.com/docs/). + +## Add a Firebase SDK to your iOS app + +CocoaPods is used to install and manage dependencies in existing Xcode projects. + +1. Create an Xcode project, and save it to your local machine. +2. Create a file named `Podfile` in your project directory. This file defines + your project's dependencies, and is commonly referred to as a Podspec. +3. Open `Podfile`, and add your dependencies. A simple Podspec is shown here: + + ``` + platform :ios, '8.0' + pod 'Firebase' + ``` + +4. Save the file. + +5. Open a terminal and `cd` to the directory containing the Podfile. + + ``` + $ cd /project/ + ``` + +6. Run the `pod install` command. This will install the SDKs specified in the + Podspec, along with any dependencies they may have. + + ``` + $ pod install + ``` + +7. Open your app's `.xcworkspace` file to launch Xcode. Use this file for all + development on your app. + +8. You can also install other Firebase SDKs by adding the subspecs in the + Podfile. + + ``` + pod 'Firebase/AdMob' + pod 'Firebase/Analytics' + pod 'Firebase/Auth' + pod 'Firebase/Database' + pod 'Firebase/DynamicLinks' + pod 'Firebase/Firestore' + pod 'Firebase/Functions' + pod 'Firebase/InAppMessaging' + pod 'Firebase/InAppMessagingDisplay' + pod 'Firebase/Messaging' + pod 'Firebase/MLCommon' + pod 'Firebase/MLModelInterpreter' + pod 'Firebase/MLNLLanguageID' + pod 'Firebase/MLNLSmartReply' + pod 'Firebase/MLNLTranslate' + pod 'Firebase/MLNaturalLanguage' + pod 'Firebase/MLVision' + pod 'Firebase/MLVisionAutoML' + pod 'Firebase/MLVisionBarcodeModel' + pod 'Firebase/MLVisionFaceModel' + pod 'Firebase/MLVisionLabelModel' + pod 'Firebase/MLVisionObjectDetection' + pod 'Firebase/MLVisionTextModel' + pod 'Firebase/Performance' + pod 'Firebase/RemoteConfig' + pod 'Firebase/Storage' + ``` diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector new file mode 100755 index 0000000..58ca891 Binary files /dev/null and b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap new file mode 100755 index 0000000..270ad21 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap @@ -0,0 +1,10 @@ +framework module FIRAnalyticsConnector { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics new file mode 100755 index 0000000..12f18f9 Binary files /dev/null and b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h new file mode 100755 index 0000000..d499af6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h @@ -0,0 +1,62 @@ +#import + +#import "FIRAnalytics.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides App Delegate handlers to be used in your App Delegate. + * + * To save time integrating Firebase Analytics in an application, Firebase Analytics does not + * require delegation implementation from the AppDelegate. Instead this is automatically done by + * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App + * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting + * it to NO, and adding the methods in this category to corresponding delegation handlers. + * + * To handle Universal Links, you must return YES in + * [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. + */ +@interface FIRAnalytics (AppDelegate) + +/** + * Handles events related to a URL session that are waiting to be processed. + * + * For optimal use of Firebase Analytics, call this method from the + * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler] + * method of the app delegate in your app. + * + * @param identifier The identifier of the URL session requiring attention. + * @param completionHandler The completion handler to call when you finish processing the events. + * Calling this completion handler lets the system know that your app's user interface is + * updated and a new snapshot can be taken. + */ ++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(nullable void (^)(void))completionHandler; + +/** + * Handles the event when the app is launched by a URL. + * + * Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and + * above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on + * iOS 8.x and below) in your app. + * + * @param url The URL resource to open. This resource can be a network resource or a file. + */ ++ (void)handleOpenURL:(NSURL *)url; + +/** + * Handles the event when the app receives data associated with user activity that includes a + * Universal Link (on iOS 9.0 and above). + * + * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app + * delegate (on iOS 9.0 and above). + * + * @param userActivity The activity object containing the data associated with the task the user + * was performing. + */ ++ (void)handleUserActivity:(id)userActivity; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h new file mode 100755 index 0000000..afb9f82 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h @@ -0,0 +1,132 @@ +#import + +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" + +NS_ASSUME_NONNULL_BEGIN + +/// The top level Firebase Analytics singleton that provides methods for logging events and setting +/// user properties. See the developer guides for general +/// information on using Firebase Analytics in your apps. +NS_SWIFT_NAME(Analytics) +@interface FIRAnalytics : NSObject + +/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have +/// the same parameters. Up to 500 event names are supported. Using predefined events and/or +/// parameters is recommended for optimal reporting. +/// +/// The following event names are reserved and cannot be used: +///
    +///
  • ad_activeview
  • +///
  • ad_click
  • +///
  • ad_exposure
  • +///
  • ad_impression
  • +///
  • ad_query
  • +///
  • adunit_exposure
  • +///
  • app_clear_data
  • +///
  • app_remove
  • +///
  • app_update
  • +///
  • error
  • +///
  • first_open
  • +///
  • in_app_purchase
  • +///
  • notification_dismiss
  • +///
  • notification_foreground
  • +///
  • notification_open
  • +///
  • notification_receive
  • +///
  • os_update
  • +///
  • screen_view
  • +///
  • session_start
  • +///
  • user_engagement
  • +///
+/// +/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or +/// underscores. The name must start with an alphabetic character. Some event names are +/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are +/// case-sensitive and that logging two events whose names differ only in case will result in +/// two distinct events. +/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has +/// no parameters. Parameter names can be up to 40 characters long and must start with an +/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString +/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are +/// supported. NSString parameter values can be up to 100 characters long. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used for parameter names. ++ (void)logEventWithName:(NSString *)name + parameters:(nullable NSDictionary *)parameters + NS_SWIFT_NAME(logEvent(_:parameters:)); + +/// Sets a user property to a given value. Up to 25 user property names are supported. Once set, +/// user property values persist throughout the app lifecycle and across sessions. +/// +/// The following user property names are reserved and cannot be used: +///
    +///
  • first_open_time
  • +///
  • last_deep_link_referrer
  • +///
  • user_id
  • +///
+/// +/// @param value The value of the user property. Values can be up to 36 characters long. Setting the +/// value to nil removes the user property. +/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters +/// or underscores and must start with an alphabetic character. The "firebase_", "google_", and +/// "ga_" prefixes are reserved and should not be used for user property names. ++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name + NS_SWIFT_NAME(setUserProperty(_:forName:)); + +/// Sets the user ID property. This feature must be used in accordance with +/// Google's Privacy Policy +/// +/// @param userID The user ID to ascribe to the user of this app on this device, which must be +/// non-empty and no more than 256 characters long. Setting userID to nil removes the user ID. ++ (void)setUserID:(nullable NSString *)userID; + +/// Sets the current screen name, which specifies the current visual context in your app. This helps +/// identify the areas in your app where users spend their time and how they interact with your app. +/// Must be called on the main thread. +/// +/// Note that screen reporting is enabled automatically and records the class name of the current +/// UIViewController for you without requiring you to call this method. If you implement +/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class +/// will not be automatically tracked. The class name can optionally be overridden by calling this +/// method in the viewDidAppear callback of your UIViewController and specifying the +/// screenClassOverride parameter. setScreenName:screenClass: must be called after +/// [super viewDidAppear:]. +/// +/// If your app does not use a distinct UIViewController for each screen, you should call this +/// method and specify a distinct screenName each time a new screen is presented to the user. +/// +/// The screen name and screen class remain in effect until the current UIViewController changes or +/// a new call to setScreenName:screenClass: is made. +/// +/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil +/// to clear the current screen name. +/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By +/// default this is the class name of the current UIViewController. Set to nil to revert to the +/// default class name. ++ (void)setScreenName:(nullable NSString *)screenName + screenClass:(nullable NSString *)screenClassOverride; + +/// Sets whether analytics collection is enabled for this app on this device. This setting is +/// persisted across app sessions. By default it is enabled. +/// +/// @param analyticsCollectionEnabled A flag that enables or disables Analytics collection. ++ (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets the interval of inactivity in seconds that terminates the current session. The default +/// value is 1800 seconds (30 minutes). +/// +/// @param sessionTimeoutInterval The custom time of inactivity in seconds before the current +/// session terminates. ++ (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval; + +/// The unique ID for this instance of the application. ++ (NSString *)appInstanceID; + +/// Clears all analytics data for this instance from the device and resets the app instance ID. +/// FIRAnalyticsConfiguration values will be reset to the default values. ++ (void)resetAnalyticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h new file mode 100755 index 0000000..c70c53e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h @@ -0,0 +1,407 @@ +/// @file FIREventNames.h +/// +/// Predefined event names. +/// +/// An Event is an important occurrence in your app that you want to measure. You can report up to +/// 500 different types of Events per app and you can associate up to 25 unique parameters with each +/// Event type. Some common events are suggested below, but you may also choose to specify custom +/// Event types that are associated with your specific app. Each event type is identified by a +/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. + +#import + +/// Add Payment Info event. This event signifies that a user has submitted their payment information +/// to your app. +static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) = + @"add_payment_info"; + +/// E-Commerce Add To Cart event. This event signifies that an item was added to a cart for +/// purchase. Add this event to a funnel with kFIREventEcommercePurchase to gauge the effectiveness +/// of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart"; + +/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist. +/// Use this event to identify popular gift items in your app. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) = + @"add_to_wishlist"; + +/// App Open event. By logging this event when an App becomes active, developers can understand how +/// often users leave and return during the course of a Session. Although Sessions are automatically +/// reported, this event can provide further clarification around the continuous engagement of +/// app-users. +static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open"; + +/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of +/// checking out. Add this event to a funnel with your kFIREventEcommercePurchase event to gauge the +/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue +/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue +/// metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) = + @"begin_checkout"; + +/// Campaign Detail event. Log this event to supply the referral details of a re-engagement +/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource, +/// kFIRParameterMedium or kFIRParameterCampaign. Params: +/// +///
    +///
  • @c kFIRParameterSource (NSString)
  • +///
  • @c kFIRParameterMedium (NSString)
  • +///
  • @c kFIRParameterCampaign (NSString)
  • +///
  • @c kFIRParameterTerm (NSString) (optional)
  • +///
  • @c kFIRParameterContent (NSString) (optional)
  • +///
  • @c kFIRParameterAdNetworkClickID (NSString) (optional)
  • +///
  • @c kFIRParameterCP1 (NSString) (optional)
  • +///
+static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) = + @"campaign_details"; + +/// Checkout progress. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString) (optional)
  • +///
+static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) = + @"checkout_progress"; + +/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log +/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy. +/// Params: +/// +///
    +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventEarnVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency"; + +/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note: +/// This is different from the in-app purchase event, which is reported automatically for App +/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also +/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterLocation (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) = + @"ecommerce_purchase"; + +/// Generate Lead event. Log this event when a lead has been generated in the app to understand the +/// efficacy of your install and re-engagement campaigns. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) = + @"generate_lead"; + +/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use +/// this event to analyze how popular certain groups or social features are in your app. Params: +/// +///
    +///
  • @c kFIRParameterGroupID (NSString)
  • +///
+static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group"; + +/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can +/// help you gauge the level distribution of your userbase and help you identify certain levels that +/// are difficult to pass. Params: +/// +///
    +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up"; + +/// Login event. Apps with a login feature can report this event to signify that a user has logged +/// in. +static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login"; + +/// Post Score event. Log this event when the user posts a score in your gaming app. This event can +/// help you understand how users are actually performing in your game and it can help you correlate +/// high scores with certain audiences or behaviors. Params: +/// +///
    +///
  • @c kFIRParameterScore (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score"; + +/// Present Offer event. This event signifies that the app has presented a purchase offer to a user. +/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge +/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) = + @"present_offer"; + +/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
+static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) = + @"purchase_refund"; + +/// Remove from cart event. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) = + @"remove_from_cart"; + +/// Search event. Apps that support search features can use this event to contextualize search +/// operations by supplying the appropriate, corresponding parameters. This event can help you +/// identify the most popular content in your app. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search"; + +/// Select Content event. This general purpose event signifies that a user has selected some content +/// of a certain type in an app. The content can be any object in your app. This event can help you +/// identify popular content and categories of content in your app. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) = + @"select_content"; + +/// Set checkout option. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString)
  • +///
+static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) = + @"set_checkout_option"; + +/// Share event. Apps with social features can log the Share event to identify the most viral +/// content. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share"; + +/// Sign Up event. This event indicates that a user has signed up for an account in your app. The +/// parameter signifies the method by which the user signed up. Use this event to understand the +/// different behaviors between logged in and logged out users. Params: +/// +///
    +///
  • @c kFIRParameterSignUpMethod (NSString)
  • +///
+static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up"; + +/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can +/// help you identify which virtual goods are the most popular objects of purchase. Params: +/// +///
    +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventSpendVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency"; + +/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use +/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this +/// process and move on to the full app experience. +static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) = + @"tutorial_begin"; + +/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding +/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your +/// on-boarding process. +static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) = + @"tutorial_complete"; + +/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your +/// game. Since achievements generally represent the breadth of a gaming experience, this event can +/// help you understand how many users are experiencing all that your game has to offer. Params: +/// +///
    +///
  • @c kFIRParameterAchievementID (NSString)
  • +///
+static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) = + @"unlock_achievement"; + +/// View Item event. This event signifies that some content was shown to the user. This content may +/// be a product, a webpage or just a simple image or text. Use the appropriate parameters to +/// contextualize the event. Use this event to discover the most popular items viewed in your app. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterFlightNumber (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterSearchTerm (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item"; + +/// View Item List event. Log this event when the user has been presented with a list of items of a +/// certain category. Params: +/// +///
    +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
+static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) = + @"view_item_list"; + +/// View Search Results event. Log this event when the user has been presented with the results of a +/// search. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
+static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) = + @"view_search_results"; + +/// Level Start event. Log this event when the user starts a new level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
+static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) = + @"level_start"; + +/// Level End event. Log this event when the user finishes a level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
  • @c kFIRParameterSuccess (NSString)
  • +///
+static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end"; diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h new file mode 100755 index 0000000..ad9fff7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h @@ -0,0 +1,532 @@ +/// @file FIRParameterNames.h +/// +/// Predefined event parameter names. +/// +/// Params supply information that contextualize Events. You can associate up to 25 unique Params +/// with each Event type. Some Params are suggested below for certain common Events, but you are +/// not limited to these. You may supply extra Params for suggested Events or custom Params for +/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. Param values can +/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and +/// should not be used. + +#import + +/// Game achievement ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) = + @"achievement_id"; + +/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format. +///
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAdNetworkClickID + NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid"; + +/// The store or affiliation from which this transaction occurred (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAffiliation : @"Google Store",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) = + @"affiliation"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Character used in game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) = + @"character"; + +/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutStep : @"1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) = + @"checkout_step"; + +/// Some option on a step in an ecommerce flow (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutOption : @"Visa",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutOption + NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option"; + +/// Campaign content (NSString). +static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content"; + +/// Type of content selected (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) = + @"content_type"; + +/// Coupon code for a purchasable item (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"zz123",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon"; + +/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign. +/// Use varies by network. +///
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1"; + +/// The name of a creative used in a promotional spot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeName : @"Summer Sale",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) = + @"creative_name"; + +/// The name of a creative slot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeSlot : @"summer_banner2",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) = + @"creative_slot"; + +/// Purchase currency in 3-letter +/// ISO_4217 format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) = + @"currency"; + +/// Flight or Travel destination (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) = + @"destination"; + +/// The arrival date, check-out date or rental end date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date"; + +/// Flight number for travel events (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) = + @"flight_number"; + +/// Group/clan/guild ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id"; + +/// Index of an item in a list (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterIndex : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index"; + +/// Item brand (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemBrand : @"Google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) = + @"item_brand"; + +/// Item category (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"t-shirts",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) = + @"item_category"; + +/// Item ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"p7654",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id"; + +/// The Google Place ID (NSString) that +/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemLocationID + NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id"; + +/// Item name (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"abc",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) = + @"item_name"; + +/// The list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemList : @"Search Results",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) = + @"item_list"; + +/// Item variant (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemVariant : @"Red",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) = + @"item_variant"; + +/// Level in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level"; + +/// Location (NSString). The Google Place ID +/// that corresponds to the associated event. Alternatively, you can supply your own custom +/// Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) = + @"location"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// Number of nights staying at hotel (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfNights + NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights"; + +/// Number of passengers traveling (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfPassengers + NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers"; + +/// Number of rooms for travel events (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) = + @"number_of_rooms"; + +/// Flight or Travel origin (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin"; + +/// Purchase price (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price"; + +/// Purchase quantity (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) = + @"quantity"; + +/// Score in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score"; + +/// The search string/keywords used (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) = + @"search_term"; + +/// Shipping cost (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(9.50),
+///       kFIRParameterCurrency : @"USD",  // e.g. $9.50 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) = + @"shipping"; + +/// Sign up method (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// 
+/// +/// This constant has been deprecated. Use Method constant instead. +static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) = + @"sign_up_method"; + +/// A particular approach used in an operation; for example, "facebook" or "email" in the context +/// of a sign_up or login event. (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMethod : @"google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMethod NS_SWIFT_NAME(AnalyticsParameterMethod) = @"method"; + +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The departure date, check-in date or rental start date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) = + @"start_date"; + +/// Tax amount (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax"; + +/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term"; + +/// A single ID for a ecommerce group transaction (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"ab7236dd9823",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) = + @"transaction_id"; + +/// Travel class (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) = + @"travel_class"; + +/// A context-specific numeric value which is accumulated automatically for each event type. This is +/// a general purpose parameter that is useful for accumulating a key metric that pertains to an +/// event. Examples include revenue, distance, time and points. Value should be specified as signed +/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events +/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be +/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is +/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the +/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid +/// currency code for conversion events will cause that +/// conversion to be omitted from reporting. +///
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value"; + +/// Name of virtual currency type (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterVirtualCurrencyName + NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name"; + +/// The name of a level in a game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevelName : @"room_1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) = + @"level_name"; + +/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned +/// integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSuccess : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success"; + +/// Indicates that the associated event should either extend the current session +/// or start a new session if no session was active when the event was logged. +/// Specify YES to extend the current session or to start a new session; any +/// other value will not extend or start a session. +///
+///     NSDictionary *params = @{
+///       kFIRParameterExtendSession : @YES,
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterExtendSession NS_SWIFT_NAME(AnalyticsParameterExtendSession) = + @"extend_session"; diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h new file mode 100755 index 0000000..132aef7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h @@ -0,0 +1,29 @@ +/// @file FIRUserPropertyNames.h +/// +/// Predefined user property names. +/// +/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can +/// later analyze different behaviors of various segments of your userbase. You may supply up to 25 +/// unique UserProperties per app, and you can use the name and value of your choosing for each one. +/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and +/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to +/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not +/// be used. + +#import + +/// The method used to sign in. For example, "google", "facebook" or "twitter". +static NSString *const kFIRUserPropertySignUpMethod + NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method"; + +/// Indicates whether events logged by Google Analytics can be used to personalize ads for the user. +/// Set to "YES" to enable, or "NO" to disable. Default is enabled. See the +/// documentation for +/// more details and information about related settings. +/// +///
+///     [FIRAnalytics setUserPropertyString:@"NO"
+///                                 forName:kFIRUserPropertyAllowAdPersonalizationSignals];
+/// 
+static NSString *const kFIRUserPropertyAllowAdPersonalizationSignals + NS_SWIFT_NAME(AnalyticsUserPropertyAllowAdPersonalizationSignals) = @"allow_personalized_ads"; diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h new file mode 100755 index 0000000..ed7588a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h @@ -0,0 +1,5 @@ +#import "FIRAnalytics+AppDelegate.h" +#import "FIRAnalytics.h" +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap new file mode 100755 index 0000000..6118e37 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module FirebaseAnalytics { + umbrella header "FirebaseAnalytics.h" + export * + module * { export * } + link "sqlite3" + link "z" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics new file mode 100755 index 0000000..559016b Binary files /dev/null and b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics differ diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/Modules/module.modulemap b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/Modules/module.modulemap new file mode 100755 index 0000000..7bfc4b2 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/Modules/module.modulemap @@ -0,0 +1,9 @@ +framework module FirebaseCoreDiagnostics { + export * + module * { export * } + link "z" + link framework "Foundation" + link framework "Security" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h new file mode 100644 index 0000000..a5143c5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h @@ -0,0 +1,60 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAConditionalUserProperty; +@protocol FIRAnalyticsInteropListener; + +NS_ASSUME_NONNULL_BEGIN + +/// Connector for bridging communication between Firebase SDKs and FirebaseAnalytics API. +@protocol FIRAnalyticsInterop + +/// Sets user property when trigger event is logged. This API is only available in the SDK. +- (void)setConditionalUserProperty:(FIRAConditionalUserProperty *)conditionalUserProperty; + +/// Clears user property if set. +- (void)clearConditionalUserProperty:(NSString *)userPropertyName + clearEventName:(NSString *)clearEventName + clearEventParameters:(NSDictionary *)clearEventParameters; + +/// Returns currently set user properties. +- (NSArray *)conditionalUserProperties:(NSString *)origin + propertyNamePrefix: + (NSString *)propertyNamePrefix; + +/// Returns the maximum number of user properties. +- (NSInteger)maxUserProperties:(NSString *)origin; + +/// Logs events. +- (void)logEventWithOrigin:(NSString *)origin + name:(NSString *)name + parameters:(nullable NSDictionary *)parameters; + +/// Sets user property. +- (void)setUserPropertyWithOrigin:(NSString *)origin name:(NSString *)name value:(id)value; + +/// Registers an Analytics listener for the given origin. +- (void)registerAnalyticsListener:(id)listener + withOrigin:(NSString *)origin; + +/// Unregisters an Analytics listener for the given origin. +- (void)unregisterAnalyticsListenerWithOrigin:(NSString *)origin; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h new file mode 100644 index 0000000..45cde55 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// Handles events and messages from Analytics. +@protocol FIRAnalyticsInteropListener + +/// Triggers when an Analytics event happens for the registered origin with +/// `FIRAnalyticsInterop`s `registerAnalyticsListener:withOrigin:`. +- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters; + +@end \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h new file mode 100644 index 0000000..efc54ab --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// @file FIRInteropEventNames.h + +#import + +/// Notification open event name. +static NSString *const kFIRIEventNotificationOpen = @"_no"; + +/// Notification foreground event name. +static NSString *const kFIRIEventNotificationForeground = @"_nf"; + +/// Campaign event name. +static NSString *const kFIRIEventFirebaseCampaign = @"_cmp"; diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h new file mode 100644 index 0000000..ae440be --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// @file FIRInteropParameterNames.h +/// +/// Predefined event parameter names used by Firebase. This file is a subset of the +/// FirebaseAnalytics FIRParameterNames.h public header. +/// +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRIParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRIParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRIParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Message identifier. +static NSString *const kFIRIParameterMessageIdentifier = @"_nmid"; + +/// Message name. +static NSString *const kFIRIParameterMessageName = @"_nmn"; + +/// Message send time. +static NSString *const kFIRIParameterMessageTime = @"_nmt"; + +/// Message device time. +static NSString *const kFIRIParameterMessageDeviceTime = @"_ndt"; + +/// Topic message. +static NSString *const kFIRIParameterTopic = @"_nt"; + +/// Stores the message_id of the last notification opened by the app. +static NSString *const kFIRIUserPropertyLastNotification = @"_ln"; diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/LICENSE b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/README.md b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/README.md new file mode 100644 index 0000000..bfaceeb --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseAnalyticsInterop/README.md @@ -0,0 +1,193 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInAppMessagingDisplay, FirebaseMessaging and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +FirebaseAuth, FirebaseCore, FirebaseDatabase and FirebaseStorage now compile, run unit tests, and +work on macOS and tvOS, thanks to contributions from the community. There are a few tweaks needed, +like ensuring iOS-only, macOS-only, or tvOS-only code is correctly guarded with checks for +`TARGET_OS_IOS`, `TARGET_OS_OSX` and `TARGET_OS_TV`. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +For installation instructions, see [above](README.md#accessing-firebase-source-snapshots). + +Note that the Firebase pod is not available for macOS and tvOS. Install a selection of the +`FirebaseAuth`, `FirebaseCore`, `FirebaseDatabase` and `FirebaseStorage` CocoaPods. + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m new file mode 100644 index 0000000..a57936b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m @@ -0,0 +1,62 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "Private/FIRAnalyticsConfiguration.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +@implementation FIRAnalyticsConfiguration +#pragma clang diagnostic pop + ++ (FIRAnalyticsConfiguration *)sharedInstance { + static FIRAnalyticsConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRAnalyticsConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (void)postNotificationName:(NSString *)name value:(id)value { + if (!name.length || !value) { + return; + } + [[NSNotificationCenter defaultCenter] postNotificationName:name + object:self + userInfo:@{name : value}]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled { + [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist { + // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO. + FIRAnalyticsEnabledState analyticsEnabledState = + analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo; + if (shouldPersist) { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:@(analyticsEnabledState) + forKey:kFIRAPersistedConfigMeasurementEnabledStateKey]; + [userDefaults synchronize]; + } + + [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification + value:@(analyticsCollectionEnabled)]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRApp.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRApp.m new file mode 100644 index 0000000..d3b6c46 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRApp.m @@ -0,0 +1,825 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#import "FIRApp.h" +#import "Private/FIRAnalyticsConfiguration.h" +#import "Private/FIRAppInternal.h" +#import "Private/FIRBundleUtil.h" +#import "Private/FIRComponentContainerInternal.h" +#import "Private/FIRConfigurationInternal.h" +#import "Private/FIRLibrary.h" +#import "Private/FIRLogger.h" +#import "Private/FIROptionsInternal.h" + +NSString *const kFIRServiceAdMob = @"AdMob"; +NSString *const kFIRServiceAuth = @"Auth"; +NSString *const kFIRServiceAuthUI = @"AuthUI"; +NSString *const kFIRServiceCrash = @"Crash"; +NSString *const kFIRServiceDatabase = @"Database"; +NSString *const kFIRServiceDynamicLinks = @"DynamicLinks"; +NSString *const kFIRServiceFirestore = @"Firestore"; +NSString *const kFIRServiceFunctions = @"Functions"; +NSString *const kFIRServiceInstanceID = @"InstanceID"; +NSString *const kFIRServiceInvites = @"Invites"; +NSString *const kFIRServiceMessaging = @"Messaging"; +NSString *const kFIRServiceMeasurement = @"Measurement"; +NSString *const kFIRServicePerformance = @"Performance"; +NSString *const kFIRServiceRemoteConfig = @"RemoteConfig"; +NSString *const kFIRServiceStorage = @"Storage"; +NSString *const kGGLServiceAnalytics = @"Analytics"; +NSString *const kGGLServiceSignIn = @"SignIn"; + +NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT"; +NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification"; +NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification"; +NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey"; +NSString *const kFIRAppNameKey = @"FIRAppNameKey"; +NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey"; + +NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat = + @"/google/firebase/global_data_collection_enabled:%@"; +NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey = + @"FirebaseDataCollectionDefaultEnabled"; + +NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification"; + +NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType"; +NSString *const kFIRAppDiagnosticsErrorKey = @"Error"; +NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp"; +NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName"; +NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion"; + +// Auth internal notification notification and key. +NSString *const FIRAuthStateDidChangeInternalNotification = + @"FIRAuthStateDidChangeInternalNotification"; +NSString *const FIRAuthStateDidChangeInternalNotificationAppKey = + @"FIRAuthStateDidChangeInternalNotificationAppKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = + @"FIRAuthStateDidChangeInternalNotificationTokenKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey = + @"FIRAuthStateDidChangeInternalNotificationUIDKey"; + +/** + * The URL to download plist files. + */ +static NSString *const kPlistURL = @"https://console.firebase.google.com/"; + +/** + * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle + * events from Core. + */ +static NSMutableArray> *sRegisteredAsConfigurable; + +@interface FIRApp () + +#ifdef DEBUG +@property(nonatomic) BOOL alreadyOutputDataCollectionFlag; +#endif // DEBUG + +@end + +@implementation FIRApp + +// This is necessary since our custom getter prevents `_options` from being created. +@synthesize options = _options; + +static NSMutableDictionary *sAllApps; +static FIRApp *sDefaultApp; +static NSMutableDictionary *sLibraryVersions; + ++ (void)configure { + FIROptions *options = [FIROptions defaultOptions]; + if (!options) { + // Read the Info.plist to see if the flag is set. At this point we can't check any user defaults + // since the app isn't configured at all, so only rely on the Info.plist value. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue == nil || [collectionEnabledPlistValue boolValue]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore), + kFIRAppDiagnosticsErrorKey : [FIRApp errorForMissingOptions] + }]; + } + + [NSException raise:kFirebaseCoreErrorDomain + format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find " + @"a valid GoogleService-Info.plist in your project. Please download one " + @"from %@.", + kPlistURL]; + } + [FIRApp configureWithOptions:options]; +#if TARGET_OS_OSX || TARGET_OS_TV + FIRLogNotice(kFIRLoggerCore, @"I-COR000028", + @"tvOS and macOS SDK support is not part of the official Firebase product. " + @"Instead they are community supported. Details at " + @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md."); +#endif +} + ++ (void)configureWithOptions:(FIROptions *)options { + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Options is nil. Please pass a valid options."]; + } + [FIRApp configureWithName:kFIRDefaultAppName options:options]; +} + ++ (void)configureWithName:(NSString *)name options:(FIROptions *)options { + if (!name || !options) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."]; + } + if (name.length == 0) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."]; + } + + if ([name isEqualToString:kFIRDefaultAppName]) { + if (sDefaultApp) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Default app has already been configured."]; + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app."); + } else { + // Validate the app name and ensure it hasn't been configured already. + for (NSUInteger charIndex = 0; charIndex < name.length; charIndex++) { + char character = [name characterAtIndex:charIndex]; + if (!((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || character == '_' || character == '-')) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App name can only contain alphanumeric (A-Z,a-z,0-9), " + @"hyphen (-), and underscore (_) characters"]; + } + } + + @synchronized(self) { + if (sAllApps && sAllApps[name]) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", name]; + } + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name); + } + + @synchronized(self) { + FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options]; + if (app.isDefaultApp) { + sDefaultApp = app; + } + + [FIRApp addAppToAppDictionary:app]; + [FIRApp sendNotificationsToSDKs:app]; + } +} + ++ (FIRApp *)defaultApp { + if (sDefaultApp) { + return sDefaultApp; + } + FIRLogError(kFIRLoggerCore, @"I-COR000003", + @"The default Firebase app has not yet been " + @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your " + @"application initialization. Read more: https://goo.gl/ctyzm8."); + return nil; +} + ++ (FIRApp *)appNamed:(NSString *)name { + @synchronized(self) { + if (sAllApps) { + FIRApp *app = sAllApps[name]; + if (app) { + return app; + } + } + FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name); + return nil; + } +} + ++ (NSDictionary *)allApps { + @synchronized(self) { + if (!sAllApps) { + FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet."); + } + return [sAllApps copy]; + } +} + +// Public only for tests ++ (void)resetApps { + @synchronized(self) { + sDefaultApp = nil; + [sAllApps removeAllObjects]; + sAllApps = nil; + [sLibraryVersions removeAllObjects]; + sLibraryVersions = nil; + } +} + +- (void)deleteApp:(FIRAppVoidBoolCallback)completion { + @synchronized([self class]) { + if (sAllApps && sAllApps[self.name]) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name); + + // Remove all cached instances from the container before deleting the app. + [self.container removeAllCachedInstances]; + + [sAllApps removeObjectForKey:self.name]; + [self clearDataCollectionSwitchFromUserDefaults]; + if ([self.name isEqualToString:kFIRDefaultAppName]) { + sDefaultApp = nil; + } + NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name}; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification + object:[self class] + userInfo:appInfoDict]; + completion(YES); + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist."); + completion(NO); + } + } +} + ++ (void)addAppToAppDictionary:(FIRApp *)app { + if (!sAllApps) { + sAllApps = [NSMutableDictionary dictionary]; + } + if ([app configureCore]) { + sAllApps[app.name] = app; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in " + @"GoogleService-Info.plist or set in the customized options."]; + } +} + +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options { + self = [super init]; + if (self) { + _name = [name copy]; + _options = [options copy]; + _options.editingLocked = YES; + _isDefaultApp = [name isEqualToString:kFIRDefaultAppName]; + _container = [[FIRComponentContainer alloc] initWithApp:self]; + } + return self; +} + +- (BOOL)configureCore { + [self checkExpectedBundleID]; + if (![self isAppIDValid]) { + if (_options.usingOptionsFromDefaultPlist && [self isDataCollectionDefaultEnabled]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore), + kFIRAppDiagnosticsErrorKey : [FIRApp errorForInvalidAppID], + }]; + } + return NO; + } + + if ([self isDataCollectionDefaultEnabled]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore), + kFIRAppDiagnosticsFIRAppKey : self + }]; + } + +#if TARGET_OS_IOS + // Initialize the Analytics once there is a valid options under default app. Analytics should + // always initialize first by itself before the other SDKs. + if ([self.name isEqualToString:kFIRDefaultAppName]) { + Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics"); + if (firAnalyticsClass) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:); +#pragma clang diagnostic pop + if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [firAnalyticsClass performSelector:startWithConfigurationSelector + withObject:[FIRConfiguration sharedInstance].analyticsConfiguration + withObject:_options]; +#pragma clang diagnostic pop + } + } + } +#endif + + return YES; +} + +- (FIROptions *)options { + return [_options copy]; +} + +- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled { +#ifdef DEBUG + FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.", + dataCollectionDefaultEnabled ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; +#endif // DEBUG + + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key]; + + // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set + // within FIROptions and change the Analytics value if necessary. Analytics only works with the + // default app, so return if this isn't the default app. + if (!self.isDefaultApp) { + return; + } + + // Check if the Analytics flag is explicitly set. If so, no further actions are necessary. + if ([self.options isAnalyticsCollectionExpicitlySet]) { + return; + } + + // The Analytics flag has not been explicitly set, so update with the value being set. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[FIRAnalyticsConfiguration sharedInstance] + setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled + persistSetting:NO]; +#pragma clang diagnostic pop +} + +- (BOOL)isDataCollectionDefaultEnabled { + // Check if it's been manually set before in code, and use that as the higher priority value. + NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self]; + if (defaultsObject != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.", + [defaultsObject boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [defaultsObject boolValue]; + } + + // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`. + // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has + // no performance impact calling multiple times. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.", + [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [collectionEnabledPlistValue boolValue]; + } + +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set."); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return YES; +} + +#pragma mark - private + ++ (void)sendNotificationsToSDKs:(FIRApp *)app { + // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`. + NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp]; + NSDictionary *appInfoDict = @{ + kFIRAppNameKey : app.name, + kFIRAppIsDefaultAppKey : isDefaultApp, + kFIRGoogleAppIDKey : app.options.googleAppID + }; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification + object:self + userInfo:appInfoDict]; + + // This is the new way of sending information to SDKs. + // TODO: Do we want this on a background thread, maybe? + @synchronized(self) { + for (Class library in sRegisteredAsConfigurable) { + [library configureWithApp:app]; + } + } +} + ++ (NSError *)errorForMissingOptions { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : + @"Unable to parse GoogleService-Info.plist in order to configure services.", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidPlistFile + userInfo:errorDict]; +} + ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", service]; + NSDictionary *errorDict = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + return [NSError errorWithDomain:domain code:code userInfo:errorDict]; +} + ++ (NSError *)errorForInvalidAppID { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : @"Unable to validate Google App ID", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the " + @"customized options." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidAppID + userInfo:errorDict]; +} + ++ (BOOL)isDefaultAppConfigured { + return (sDefaultApp != nil); +} + ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version { + // Create the set of characters which aren't allowed, only if this feature is used. + NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedSet addCharactersInString:@"-_."]; + NSCharacterSet *disallowedSet = [allowedSet invertedSet]; + // Make sure the library name and version strings do not contain unexpected characters, and + // add the name/version pair to the dictionary. + if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound && + [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) { + @synchronized(self) { + if (!sLibraryVersions) { + sLibraryVersions = [[NSMutableDictionary alloc] init]; + } + sLibraryVersions[name] = version; + } + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000027", + @"The library name (%@) or version number (%@) contain invalid characters. " + @"Only alphanumeric, dash, underscore and period characters are allowed.", + name, version); + } +} + ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version { + // This is called at +load time, keep the work to a minimum. + + // Ensure the class given conforms to the proper protocol. + if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] || + ![(Class)library respondsToSelector:@selector(componentsToRegister)]) { + [NSException raise:NSInvalidArgumentException + format:@"Class %@ attempted to register components, but it does not conform to " + @"`FIRLibrary or provide a `componentsToRegister:` method.", + library]; + } + + [FIRComponentContainer registerAsComponentRegistrant:library]; + if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRegisteredAsConfigurable = [[NSMutableArray alloc] init]; + }); + @synchronized(self) { + [sRegisteredAsConfigurable addObject:library]; + } + } + [self registerLibrary:name withVersion:version]; +} + ++ (NSString *)firebaseUserAgent { + @synchronized(self) { + NSMutableArray *libraries = + [[NSMutableArray alloc] initWithCapacity:sLibraryVersions.count]; + for (NSString *libraryName in sLibraryVersions) { + [libraries addObject:[NSString stringWithFormat:@"%@/%@", libraryName, + sLibraryVersions[libraryName]]]; + } + [libraries sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + return [libraries componentsJoinedByString:@" "]; + } +} + +- (void)checkExpectedBundleID { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *expectedBundleID = [self expectedBundleID]; + // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for + // backward compatibility. + if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID + inBundles:bundles]) { + FIRLogError(kFIRLoggerCore, @"I-COR000008", + @"The project's Bundle ID is inconsistent with " + @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are " + @"using a customized options. To ensure that everything can be configured " + @"correctly, you may need to make the Bundle IDs consistent. To continue with this " + @"plist file, you may change your app's bundle identifier to '%@'. Or you can " + @"download a new configuration file that matches your bundle identifier from %@ " + @"and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + } +} + +#pragma mark - private - App ID Validation + +/** + * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file. + * This is the main method for validating app ID. + * + * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise. + */ +- (BOOL)isAppIDValid { + NSString *appID = _options.googleAppID; + BOOL isValid = [FIRApp validateAppID:appID]; + if (!isValid) { + NSString *expectedBundleID = [self expectedBundleID]; + FIRLogError(kFIRLoggerCore, @"I-COR000009", + @"The GOOGLE_APP_ID either in the plist file " + @"'%@.%@' or the one set in the customized options is invalid. If you are using " + @"the plist file, use the iOS version of bundle identifier to download the file, " + @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle " + @"identifier to '%@'. Or you can download a new configuration file that matches " + @"your bundle identifier from %@ and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + }; + return isValid; +} + ++ (BOOL)validateAppID:(NSString *)appID { + // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not + // have a valid fingerprint, otherwise we just warn about the potential issue. + if (!appID.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + NSString *appIDVersion; + if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] + intoString:&appIDVersion]) { + return NO; + } + + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + NSArray *knownVersions = @[ @"1" ]; + if (![knownVersions containsObject:appIDVersion]) { + // Permit unknown yet properly formatted app ID versions. + FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion); + return YES; + } + + if (![self validateAppIDFormat:appID withVersion:appIDVersion]) { + return NO; + } + + if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) { + return NO; + } + + return YES; +} + ++ (NSString *)actualBundleID { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +/** + * Validates that the format of the app ID string is what is expected based on the supplied version. + * The version must end in ":". + * + * For v1 app ids the format is expected to be + * '::ios:'. + * + * This method does not verify that the contents of the app id are correct, just that they fulfill + * the expected format. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected format, NO otherwise. + */ ++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { + if (!appID.length || !version.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + // Skip version part + // '**::ios:' + if (![stringScanner scanString:version intoString:NULL]) { + // The version part is missing or mismatched + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '*:*:ios:' + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':**:ios:'. + NSInteger projectNumber = NSNotFound; + if (![stringScanner scanInteger:&projectNumber]) { + // NO project number found. + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':*:*ios:'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The project number must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::*ios*:'. + NSString *platform; + if (![stringScanner scanUpToString:@":" intoString:&platform]) { + return NO; + } + + if (![platform isEqualToString:@"ios"]) { + // The platform must be @"ios" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios*:*'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The platform must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios:**'. + unsigned long long fingerprint = NSNotFound; + if (![stringScanner scanHexLongLong:&fingerprint]) { + // Fingerprint part is missing + return NO; + } + + if (!stringScanner.isAtEnd) { + // There are not allowed characters in the fingerprint part + return NO; + } + + return YES; +} + +/** + * Validates that the fingerprint of the app ID string is what is expected based on the supplied + * version. + * + * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected fingerprint and the version is known, NO + * otherwise. + */ ++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version { + // Extract the supplied fingerprint from the supplied app ID. + // This assumes the app ID format is the same for all known versions below. If the app ID format + // changes in future versions, the tokenizing of the app ID format will need to take into account + // the version of the app ID. + NSArray *components = [appID componentsSeparatedByString:@":"]; + if (components.count != 4) { + return NO; + } + + NSString *suppliedFingerprintString = components[3]; + if (!suppliedFingerprintString.length) { + return NO; + } + + uint64_t suppliedFingerprint; + NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString]; + if (![scanner scanHexLongLong:&suppliedFingerprint]) { + return NO; + } + + if ([version isEqual:@"1"]) { + // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated. + return YES; + } + + // Unknown version. + return NO; +} + +- (NSString *)expectedBundleID { + return _options.bundleID; +} + +// end App ID validation + +#pragma mark - Reading From Plist & User Defaults + +/** + * Clears the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ +- (void)clearDataCollectionSwitchFromUserDefaults { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +/** + * Reads the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app { + // Read the object in user defaults, and only return if it's an NSNumber. + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name]; + id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key]; + if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) { + return collectionEnabledDefaultsObject; + } + + return nil; +} + +/** + * Reads the data collection switch from the Info.plist for easier testing and readability. Will + * only read once from the plist and return the cached value. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromPlist { + static NSNumber *collectionEnabledPlistObject; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber. + id plistValue = [[NSBundle mainBundle] + objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey]; + if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) { + collectionEnabledPlistObject = (NSNumber *)plistValue; + } + }); + + return collectionEnabledPlistObject; +} + +#pragma mark - Sending Logs + +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error { + // If the user has manually turned off data collection, return and don't send logs. + if (![self isDataCollectionDefaultEnabled]) { + return; + } + + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeSDK), + kFIRAppDiagnosticsSDKNameKey : serviceName, + kFIRAppDiagnosticsSDKVersionKey : version, + kFIRAppDiagnosticsFIRAppKey : self + }]; + if (error) { + userInfo[kFIRAppDiagnosticsErrorKey] = error; + } + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:userInfo]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m new file mode 100644 index 0000000..2aecdab --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m @@ -0,0 +1,47 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRAppAssociationRegistration.h" + +#import + +@implementation FIRAppAssociationRegistration + ++ (nullable id)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(id _Nullable (^)(void))creationBlock { + @synchronized(self) { + SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:); + NSMutableDictionary *objectsByKey = objc_getAssociatedObject(host, dictKey); + if (!objectsByKey) { + objectsByKey = [[NSMutableDictionary alloc] init]; + objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + id obj = objectsByKey[key]; + NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey]; + if (obj) { + if ([creationBlockBeingCalled isEqual:obj]) { + [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed" + format:@"host: %@ key: %@", host, key]; + } + return obj; + } + objectsByKey[key] = creationBlockBeingCalled; + obj = creationBlock(); + objectsByKey[key] = obj; + return obj; + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m new file mode 100644 index 0000000..841833a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m @@ -0,0 +1,75 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRBundleUtil.h" + +#import + +@implementation FIRBundleUtil + ++ (NSArray *)relevantBundles { + return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ]; +} + ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles { + // Loop through all bundles to find the config dict. + for (NSBundle *bundle in bundles) { + NSString *path = [bundle pathForResource:resourceName ofType:fileType]; + // Use the first one we find. + if (path) { + return path; + } + } + return nil; +} + ++ (NSArray *)relevantURLSchemes { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (NSBundle *bundle in [[self class] relevantBundles]) { + NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]; + for (NSDictionary *urlType in urlTypes) { + [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]]; + } + } + return result; +} + ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles { + for (NSBundle *bundle in bundles) { + // This allows app extensions that have the app's bundle as their prefix to pass this test. + NSString *applicationBundleIdentifier = + [GULAppEnvironmentUtil isAppExtension] + ? [self bundleIdentifierByRemovingLastPartFrom:bundleIdentifier] + : bundleIdentifier; + + if ([applicationBundleIdentifier isEqualToString:bundle.bundleIdentifier]) { + return YES; + } + } + return NO; +} + ++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponent.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponent.m new file mode 100644 index 0000000..2474d1a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponent.m @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRComponent.h" + +#import "Private/FIRComponentContainer.h" +#import "Private/FIRDependency.h" + +@interface FIRComponent () + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock; + +@end + +@implementation FIRComponent + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; +} + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:instantiationTiming + dependencies:dependencies + creationBlock:creationBlock]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + self = [super init]; + if (self) { + _protocol = protocol; + _instantiationTiming = instantiationTiming; + _dependencies = [dependencies copy]; + _creationBlock = creationBlock; + } + return self; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m new file mode 100644 index 0000000..1977d0e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m @@ -0,0 +1,176 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRComponentContainer.h" + +#import "Private/FIRAppInternal.h" +#import "Private/FIRComponent.h" +#import "Private/FIRLibrary.h" +#import "Private/FIRLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer () + +/// The dictionary of components that are registered for a particular app. The key is an NSString +/// of the protocol. +@property(nonatomic, strong) NSMutableDictionary *components; + +/// Cached instances of components that requested to be cached. +@property(nonatomic, strong) NSMutableDictionary *cachedInstances; + +@end + +@implementation FIRComponentContainer + +// Collection of all classes that register to provide components. +static NSMutableSet *sFIRComponentRegistrants; + +#pragma mark - Public Registration + ++ (void)registerAsComponentRegistrant:(Class)klass { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sFIRComponentRegistrants = [[NSMutableSet alloc] init]; + }); + + [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants]; +} + ++ (void)registerAsComponentRegistrant:(Class)klass + inSet:(NSMutableSet *)allRegistrants { + [allRegistrants addObject:klass]; +} + +#pragma mark - Internal Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWithApp:app registrants:sFIRComponentRegistrants]; +} + +- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet *)allRegistrants { + self = [super init]; + if (self) { + _app = app; + _cachedInstances = [NSMutableDictionary dictionary]; + _components = [NSMutableDictionary dictionary]; + + [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app]; + } + return self; +} + +- (void)populateComponentsFromRegisteredClasses:(NSSet *)classes forApp:(FIRApp *)app { + // Loop through the verified component registrants and populate the components array. + for (Class klass in classes) { + // Loop through all the components being registered and store them as appropriate. + // Classes which do not provide functionality should use a dummy FIRComponentRegistrant + // protocol. + for (FIRComponent *component in [klass componentsToRegister]) { + // Check if the component has been registered before, and error out if so. + NSString *protocolName = NSStringFromProtocol(component.protocol); + if (self.components[protocolName]) { + FIRLogError(kFIRLoggerCore, @"I-COR000029", + @"Attempted to register protocol %@, but it already has an implementation.", + protocolName); + continue; + } + + // Store the creation block for later usage. + self.components[protocolName] = component.creationBlock; + + // Instantiate the + BOOL shouldInstantiateEager = + (component.instantiationTiming == FIRInstantiationTimingAlwaysEager); + BOOL shouldInstantiateDefaultEager = + (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp && + [app isDefaultApp]); + if (shouldInstantiateEager || shouldInstantiateDefaultEager) { + [self instantiateInstanceForProtocol:component.protocol withBlock:component.creationBlock]; + } + } + } +} + +#pragma mark - Instance Creation + +/// Instantiate an instance of a class that conforms to the specified protocol. +/// This will: +/// - Call the block to create an instance if possible, +/// - Validate that the instance returned conforms to the protocol it claims to, +/// - Cache the instance if the block requests it +- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol + withBlock:(FIRComponentCreationBlock)creationBlock { + if (!creationBlock) { + return nil; + } + + // Create an instance using the creation block. + BOOL shouldCache = NO; + id instance = creationBlock(self, &shouldCache); + if (!instance) { + return nil; + } + + // An instance was created, validate that it conforms to the protocol it claims to. + NSString *protocolName = NSStringFromProtocol(protocol); + if (![instance conformsToProtocol:protocol]) { + FIRLogError(kFIRLoggerCore, @"I-COR000030", + @"An instance conforming to %@ was requested, but the instance provided does not " + @"conform to the protocol", + protocolName); + } + + // The instance is ready to be returned, but check if it should be cached first before returning. + if (shouldCache) { + self.cachedInstances[protocolName] = instance; + } + + return instance; +} + +#pragma mark - Internal Retrieval + +- (nullable id)instanceForProtocol:(Protocol *)protocol { + // Check if there is a cached instance, and return it if so. + NSString *protocolName = NSStringFromProtocol(protocol); + id cachedInstance = self.cachedInstances[protocolName]; + if (cachedInstance) { + return cachedInstance; + } + + // Use the creation block to instantiate an instance and return it. + FIRComponentCreationBlock creationBlock = self.components[protocolName]; + return [self instantiateInstanceForProtocol:protocol withBlock:creationBlock]; +} + +#pragma mark - Lifecycle + +- (void)removeAllCachedInstances { + // Loop through the cache and notify each instance that is a maintainer to clean up after itself. + for (id instance in self.cachedInstances.allValues) { + if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] && + [instance respondsToSelector:@selector(appWillBeDeleted:)]) { + [instance appWillBeDeleted:self.app]; + } + } + + [self.cachedInstances removeAllObjects]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m new file mode 100644 index 0000000..bdc004f --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRComponentType.h" + +#import "Private/FIRComponentContainerInternal.h" + +@implementation FIRComponentType + ++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container { + // Forward the call to the container. + return [container instanceForProtocol:protocol]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m new file mode 100644 index 0000000..869f73d --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m @@ -0,0 +1,46 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRConfigurationInternal.h" + +#import "Private/FIRAnalyticsConfiguration.h" + +extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +@implementation FIRConfiguration + ++ (instancetype)sharedInstance { + static FIRConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance]; + } + return self; +} + +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel { + NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin, + @"Invalid logger level, %ld", (long)loggerLevel); + FIRSetLoggerLevel(loggerLevel); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRDependency.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRDependency.m new file mode 100644 index 0000000..f979984 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRDependency.m @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRDependency.h" + +@interface FIRDependency () + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +@end + +@implementation FIRDependency + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol { + return [[self alloc] initWithProtocol:protocol isRequired:YES]; +} + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + return [[self alloc] initWithProtocol:protocol isRequired:required]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + self = [super init]; + if (self) { + _protocol = protocol; + _isRequired = required; + } + return self; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRErrors.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRErrors.m new file mode 100644 index 0000000..72120c5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRErrors.m @@ -0,0 +1,21 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRErrors.h" + +NSString *const kFirebaseErrorDomain = @"com.firebase"; +NSString *const kFirebaseConfigErrorDomain = @"com.firebase.config"; +NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core"; +NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf"; +NSString *const kFirebaseStorageErrorDomain = @"com.firebase.storage"; diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRLogger.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRLogger.m new file mode 100644 index 0000000..532a96c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRLogger.m @@ -0,0 +1,179 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRLogger.h" + +#import +#import +#import + +#import "Private/FIRVersion.h" + +FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]"; + +// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones! +FIRLoggerService kFIRLoggerABTesting = @"[Firebase/ABTesting]"; +FIRLoggerService kFIRLoggerAdMob = @"[Firebase/AdMob]"; +FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]"; +FIRLoggerService kFIRLoggerAuth = @"[Firebase/Auth]"; +FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]"; +FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]"; +FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]"; +FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]"; + +/// Arguments passed on launch. +NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled"; +NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled"; +NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR"; + +/// Key for the debug mode bit in NSUserDefaults. +NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode"; + +/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults` +/// will be used. +static NSUserDefaults *sFIRLoggerUserDefaults; + +static dispatch_once_t sFIRLoggerOnceToken; + +// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled +// flags used by Analytics. Users who use those flags expect Analytics to log verbosely, +// while the rest of Firebase logs at the default level. This flag is introduced to support +// that behavior. +static BOOL sFIRAnalyticsDebugMode; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void FIRLoggerInitializeASL() { + dispatch_once(&sFIRLoggerOnceToken, ^{ + // Register Firebase Version with GULLogger. + GULLoggerRegisterVersion(FIRVersionString); + + // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in. + NSArray *arguments = [NSProcessInfo processInfo].arguments; + BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument]; + + // Use the standard NSUserDefaults if it hasn't been explicitly set. + if (sFIRLoggerUserDefaults == nil) { + sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults]; + } + + BOOL forceDebugMode = NO; + BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey]; + if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) { // Default mode + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] || + debugMode) { // Debug mode + [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey]; + forceDebugMode = YES; + } + GULLoggerInitializeASL(); + if (overrideSTDERR) { + GULLoggerEnableSTDERR(); + } + if (forceDebugMode) { + GULLoggerForceDebug(); + } + }); +} + +__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) { + sFIRAnalyticsDebugMode = analyticsDebugMode; +} + +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) { + FIRLoggerInitializeASL(); + GULSetLoggerLevel((GULLoggerLevel)loggerLevel); +} + +#ifdef DEBUG +void FIRResetLogger() { + extern void GULResetLogger(void); + sFIRLoggerOnceToken = 0; + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + sFIRLoggerUserDefaults = nil; + GULResetLogger(); +} + +void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) { + sFIRLoggerUserDefaults = defaults; +} +#endif + +/** + * Check if the level is high enough to be loggable. + * + * Analytics can override the log level with an intentional race condition. + * Add the attribute to get a clean thread sanitizer run. + */ +__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, + BOOL analyticsComponent) { + FIRLoggerInitializeASL(); + if (sFIRAnalyticsDebugMode && analyticsComponent) { + return YES; + } + return GULIsLoggableLevel((GULLoggerLevel)loggerLevel); +} + +void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + FIRLoggerInitializeASL(); + GULLogBasic((GULLoggerLevel)level, service, + sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode, + message, args_ptr); +} + +/** + * Generates the logging functions using macros. + * + * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure blah failed. + * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure succeed. + */ +#define FIR_LOGGING_FUNCTION(level) \ + void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +FIR_LOGGING_FUNCTION(Error) +FIR_LOGGING_FUNCTION(Warning) +FIR_LOGGING_FUNCTION(Notice) +FIR_LOGGING_FUNCTION(Info) +FIR_LOGGING_FUNCTION(Debug) + +#undef FIR_MAKE_LOGGER + +#pragma mark - FIRLoggerWrapper + +@implementation FIRLoggerWrapper + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + FIRLogBasic(level, service, messageCode, message, args); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIROptions.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIROptions.m new file mode 100644 index 0000000..3e6a3a0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIROptions.m @@ -0,0 +1,448 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRAppInternal.h" +#import "Private/FIRBundleUtil.h" +#import "Private/FIRErrors.h" +#import "Private/FIRLogger.h" +#import "Private/FIROptionsInternal.h" +#import "Private/FIRVersion.h" + +// Keys for the strings in the plist file. +NSString *const kFIRAPIKey = @"API_KEY"; +NSString *const kFIRTrackingID = @"TRACKING_ID"; +NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID"; +NSString *const kFIRClientID = @"CLIENT_ID"; +NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID"; +NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID"; +NSString *const kFIRDatabaseURL = @"DATABASE_URL"; +NSString *const kFIRStorageBucket = @"STORAGE_BUCKET"; +// The key to locate the expected bundle identifier in the plist file. +NSString *const kFIRBundleID = @"BUNDLE_ID"; +// The key to locate the project identifier in the plist file. +NSString *const kFIRProjectID = @"PROJECT_ID"; + +NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED"; + +NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED"; +NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED"; + +// Library version ID formatted like: +// @"5" // Major version (one or more digits) +// @"04" // Minor version (exactly 2 digits) +// @"01" // Build number (exactly 2 digits) +// @"000"; // Fixed "000" +NSString *kFIRLibraryVersionID; + +// Plist file name. +NSString *const kServiceInfoFileName = @"GoogleService-Info"; +// Plist file type. +NSString *const kServiceInfoFileType = @"plist"; + +// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp. +NSString *const kFIRExceptionBadModification = + @"Attempted to modify options after it's set on FIRApp. Please modify all properties before " + @"initializing FIRApp."; + +@interface FIROptions () + +/** + * This property maintains the actual configuration key-value pairs. + */ +@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary; + +/** + * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary. + * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the main plist override values from the GoogleService-Info.plist. + */ +@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary; + +/** + * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the infoDictionary override values from the GoogleService-Info.plist. + */ +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary; + +/** + * Throw exception if editing is locked when attempting to modify an option. + */ +- (void)checkEditingLocked; + +@end + +@implementation FIROptions { + /// Backing variable for self.analyticsOptionsDictionary. + NSDictionary *_analyticsOptionsDictionary; +} + +static FIROptions *sDefaultOptions = nil; +static NSDictionary *sDefaultOptionsDictionary = nil; + +#pragma mark - Public only for internal class methods + ++ (FIROptions *)defaultOptions { + if (sDefaultOptions != nil) { + return sDefaultOptions; + } + + NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary]; + if (defaultOptionsDictionary == nil) { + return nil; + } + + sDefaultOptions = [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary]; + return sDefaultOptions; +} + +#pragma mark - Private class methods + ++ (void)initialize { + // Report FirebaseCore version for useragent string + [FIRApp registerLibrary:@"fire-ios" + withVersion:[NSString stringWithUTF8String:FIRCoreVersionString]]; + + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + NSString *xcodeVersion = info[@"DTXcodeBuild"]; + NSString *sdkVersion = info[@"DTSDKBuild"]; + if (xcodeVersion) { + [FIRApp registerLibrary:@"xcode" withVersion:xcodeVersion]; + } + if (sdkVersion) { + [FIRApp registerLibrary:@"apple-sdk" withVersion:sdkVersion]; + } +} + ++ (NSDictionary *)defaultOptionsDictionary { + if (sDefaultOptionsDictionary != nil) { + return sDefaultOptionsDictionary; + } + NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName]; + if (plistFilePath == nil) { + return nil; + } + sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath]; + if (sDefaultOptionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000011", + @"The configuration file is not a dictionary: " + @"'%@.%@'.", + kServiceInfoFileName, kServiceInfoFileType); + } + return sDefaultOptionsDictionary; +} + +// Returns the path of the plist file with a given file name. ++ (NSString *)plistFilePathWithName:(NSString *)fileName { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *plistFilePath = + [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName + andFileType:kServiceInfoFileType + inBundles:bundles]; + if (plistFilePath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.", + fileName, kServiceInfoFileType); + } + return plistFilePath; +} + ++ (void)resetDefaultOptions { + sDefaultOptions = nil; + sDefaultOptionsDictionary = nil; +} + +#pragma mark - Private instance methods + +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary { + self = [super init]; + if (self) { + _optionsDictionary = [optionsDictionary mutableCopy]; + _usingOptionsFromDefaultPlist = YES; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + FIROptions *newOptions = [[[self class] allocWithZone:zone] init]; + if (newOptions) { + newOptions.optionsDictionary = self.optionsDictionary; + newOptions.deepLinkURLScheme = self.deepLinkURLScheme; + newOptions.editingLocked = self.isEditingLocked; + newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist; + } + return newOptions; +} + +#pragma mark - Public instance methods + +- (instancetype)initWithContentsOfFile:(NSString *)plistPath { + self = [super init]; + if (self) { + if (plistPath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil."); + return nil; + } + _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy]; + if (_optionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000014", + @"The configuration file at %@ does not exist or " + @"is not a well-formed plist file.", + plistPath); + return nil; + } + // TODO: Do we want to validate the dictionary here? It says we do that already in + // the public header. + } + return self; +} + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary]; + [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID]; + [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID]; + [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID]; + self.optionsDictionary = mutableOptionsDict; + } + return self; +} + +- (NSString *)APIKey { + return self.optionsDictionary[kFIRAPIKey]; +} + +- (void)checkEditingLocked { + if (self.isEditingLocked) { + [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification]; + } +} + +- (void)setAPIKey:(NSString *)APIKey { + [self checkEditingLocked]; + _optionsDictionary[kFIRAPIKey] = [APIKey copy]; +} + +- (NSString *)clientID { + return self.optionsDictionary[kFIRClientID]; +} + +- (void)setClientID:(NSString *)clientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRClientID] = [clientID copy]; +} + +- (NSString *)trackingID { + return self.optionsDictionary[kFIRTrackingID]; +} + +- (void)setTrackingID:(NSString *)trackingID { + [self checkEditingLocked]; + _optionsDictionary[kFIRTrackingID] = [trackingID copy]; +} + +- (NSString *)GCMSenderID { + return self.optionsDictionary[kFIRGCMSenderID]; +} + +- (void)setGCMSenderID:(NSString *)GCMSenderID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy]; +} + +- (NSString *)projectID { + return self.optionsDictionary[kFIRProjectID]; +} + +- (void)setProjectID:(NSString *)projectID { + [self checkEditingLocked]; + _optionsDictionary[kFIRProjectID] = [projectID copy]; +} + +- (NSString *)androidClientID { + return self.optionsDictionary[kFIRAndroidClientID]; +} + +- (void)setAndroidClientID:(NSString *)androidClientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy]; +} + +- (NSString *)googleAppID { + return self.optionsDictionary[kFIRGoogleAppID]; +} + +- (void)setGoogleAppID:(NSString *)googleAppID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy]; +} + +- (NSString *)libraryVersionID { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The unit tests are set up to catch anything that does not properly convert. + NSString *version = [NSString stringWithUTF8String:FIRCoreVersionString]; + NSArray *components = [version componentsSeparatedByString:@"."]; + NSString *major = [components objectAtIndex:0]; + NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]]; + NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]]; + kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch]; + }); + return kFIRLibraryVersionID; +} + +- (void)setLibraryVersionID:(NSString *)libraryVersionID { + _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy]; +} + +- (NSString *)databaseURL { + return self.optionsDictionary[kFIRDatabaseURL]; +} + +- (void)setDatabaseURL:(NSString *)databaseURL { + [self checkEditingLocked]; + + _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy]; +} + +- (NSString *)storageBucket { + return self.optionsDictionary[kFIRStorageBucket]; +} + +- (void)setStorageBucket:(NSString *)storageBucket { + [self checkEditingLocked]; + _optionsDictionary[kFIRStorageBucket] = [storageBucket copy]; +} + +- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme { + [self checkEditingLocked]; + _deepLinkURLScheme = [deepLinkURLScheme copy]; +} + +- (NSString *)bundleID { + return self.optionsDictionary[kFIRBundleID]; +} + +- (void)setBundleID:(NSString *)bundleID { + [self checkEditingLocked]; + _optionsDictionary[kFIRBundleID] = [bundleID copy]; +} + +#pragma mark - Internal instance methods + +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary { + if (_analyticsOptionsDictionary == nil) { + NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init]; + NSArray *measurementKeys = @[ + kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled, + kFIRIsAnalyticsCollectionDeactivated + ]; + for (NSString *key in measurementKeys) { + id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil; + if (!value) { + continue; + } + tempAnalyticsOptions[key] = value; + } + _analyticsOptionsDictionary = tempAnalyticsOptions; + } + return _analyticsOptionsDictionary; +} + +- (NSDictionary *)analyticsOptionsDictionary { + return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary]; +} + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still + * be supported. + */ +- (BOOL)isMeasurementEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (value == nil) { + // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have + // to check if it's the default app. The FIROptions instance can't be modified after + // `+configure` is called, so it's not a good place to copy it either in case the flag is + // changed at runtime. + + // If no values are set for Analytics, fall back to the global collection switch in FIRApp. + // Analytics only supports the default FIRApp, so check that first. + if (![FIRApp isDefaultAppConfigured]) { + return NO; + } + + // Fall back to the default app's collection switch when the key is not in the dictionary. + return [FIRApp defaultApp].isDataCollectionDefaultEnabled; + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionExpicitlySet { + // If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication + // that the developer wants FirebaseAnalytics enabled so continue checking. + if (self.isAnalyticsCollectionDeactivated) { + return YES; + } + + // Check if the current Analytics flag is set. + id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // Check if the old measurement flag is set. + id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // No flags are set to explicitly enable or disable FirebaseAnalytics. + return NO; +} + +- (BOOL)isAnalyticsCollectionEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (value == nil) { + return self.isMeasurementEnabled; // Fall back to older plist flag. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionDeactivated { + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated]; + if (value == nil) { + return NO; // Analytics Collection is not deactivated when the key is not in the dictionary. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsEnabled { + return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue]; +} + +- (BOOL)isSignInEnabled { + return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRVersion.m b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRVersion.m new file mode 100644 index 0000000..ec0f6ba --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/FIRVersion.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_VERSION +#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation" +#endif + +#ifndef FIRCore_VERSION +#error "FIRCore_VERSION is not defined: add -DFIRCore_VERSION=... to the build invocation" +#endif + +// The following two macros supply the incantation so that the C +// preprocessor does not try to parse the version as a floating +// point number. See +// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/ +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRVersionString = (const char *const)STR(Firebase_VERSION); +const char *const FIRCoreVersionString = (const char *const)STR(FIRCore_VERSION); diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h new file mode 100644 index 0000000..6429ac7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// Values stored in analyticsEnabledState. Never alter these constants since they must match with +/// values persisted to disk. +typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) { + // 0 is the default value for keys not found stored in persisted config, so it cannot represent + // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet. + kFIRAnalyticsEnabledStateNotSet = 0, + kFIRAnalyticsEnabledStateSetYes = 1, + kFIRAnalyticsEnabledStateSetNo = 2, +}; + +/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads +/// measurementEnabledState using this same key. +static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey = + @"/google/measurement/measurement_enabled_state"; + +static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification = + @"FIRAnalyticsConfigurationSetEnabledNotification"; +static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification = + @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification"; +static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification = + @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification"; + +@interface FIRAnalyticsConfiguration : NSObject + +/// Returns the shared instance of FIRAnalyticsConfiguration. ++ (FIRAnalyticsConfiguration *)sharedInstance; + +// Sets whether analytics collection is enabled for this app on this device. This setting is +// persisted across app sessions. By default it is enabled. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist +/// the value or not. The setting should not be persisted if being set by the global data collection +/// flag. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h new file mode 100644 index 0000000..3fc69c6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// TODO: Remove this once Auth moves over to Core's instance registration system. +/** @class FIRAppAssociationRegistration + @brief Manages object associations as a singleton-dependent: At most one object is + registered for any given host/key pair, and the object shall be created on-the-fly when + asked for. + */ +@interface FIRAppAssociationRegistration : NSObject + +/** @fn registeredObjectWithHost:key:creationBlock: + @brief Retrieves the registered object with a particular host and key. + @param host The host object. + @param key The key to specify the registered object on the host. + @param creationBlock The block to return the object to be registered if not already. + The block is executed immediately before this method returns if it is executed at all. + It can also be executed multiple times across different method invocations if previous + execution of the block returns @c nil. + @return The registered object for the host/key pair, or @c nil if no object is registered + and @c creationBlock returns @c nil. + @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this + method again within the @c creationBlock with the same host/key pair raises an exception. + The registered object is retained by the host. + */ ++ (nullable ObjectType)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(ObjectType _Nullable (^)(void))creationBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h new file mode 100644 index 0000000..09728cd --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h @@ -0,0 +1,180 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +/** + * Names of services provided by Firebase. + */ +extern NSString *const kFIRServiceAdMob; +extern NSString *const kFIRServiceAuth; +extern NSString *const kFIRServiceAuthUI; +extern NSString *const kFIRServiceDatabase; +extern NSString *const kFIRServiceDynamicLinks; +extern NSString *const kFIRServiceInstanceID; +extern NSString *const kFIRServiceMessaging; +extern NSString *const kFIRServiceMeasurement; +extern NSString *const kFIRServiceRemoteConfig; +extern NSString *const kFIRServiceStorage; + +/** + * Names of services provided by the Google pod, but logged by the Firebase pod. + */ +extern NSString *const kGGLServiceAnalytics; +extern NSString *const kGGLServiceSignIn; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h new file mode 100644 index 0000000..d9475dd --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * This class provides utilities for accessing resources in bundles. + */ +@interface FIRBundleUtil : NSObject + +/** + * Finds all relevant bundles, starting with [NSBundle mainBundle]. + */ ++ (NSArray *)relevantBundles; + +/** + * Reads the options dictionary from one of the provided bundles. + * + * @param resourceName The resource name, e.g. @"GoogleService-Info". + * @param fileType The file type (extension), e.g. @"plist". + * @param bundles The bundles to expect, in priority order. See also + * +[FIRBundleUtil relevantBundles]. + */ ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles; + +/** + * Finds URL schemes defined in all relevant bundles, starting with those from + * [NSBundle mainBundle]. + */ ++ (NSArray *)relevantURLSchemes; + +/** + * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension + * suffixes). + */ ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h new file mode 100644 index 0000000..cb51ee7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h new file mode 100644 index 0000000..f3dc356 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FIRComponentType.h" +#import "FIRLibrary.h" + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h new file mode 100644 index 0000000..e8552fa --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h @@ -0,0 +1,43 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FIRComponent.h" +#import "FIRComponentContainer.h" + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer (Private) + +/// Initializes a contain for a given app. This should only be called by the app itself. +- (instancetype)initWithApp:(FIRApp *)app; + +/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the +/// protocol wasn't registered, or if the instance couldn't instantiate for the provided app. +- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:)); + +/// Remove all of the cached instances stored and allow them to clean up after themselves. +- (void)removeAllCachedInstances; + +/// Register a class to provide components for the interoperability system. The class should conform +/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects. ++ (void)registerAsComponentRegistrant:(Class)klass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h new file mode 100644 index 0000000..6f2aca7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h new file mode 100644 index 0000000..ee16886 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRConfiguration.h" + +@class FIRAnalyticsConfiguration; + +@interface FIRConfiguration () + +/** + * The configuration class for Firebase Analytics. This should be removed once the logic for + * enabling and disabling Analytics is moved to Analytics. + */ +@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h new file mode 100644 index 0000000..46e9b7e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h new file mode 100644 index 0000000..f77b3d0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h new file mode 100644 index 0000000..19e4732 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h new file mode 100644 index 0000000..728c062 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import +#import "FIRComponent.h" + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h new file mode 100644 index 0000000..548e389 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h new file mode 100644 index 0000000..117efda --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h @@ -0,0 +1,114 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExpicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h new file mode 100644 index 0000000..226efb1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The version of the Firebase SDK. */ +FOUNDATION_EXPORT const char *const FIRVersionString; + +/** The version of the FirebaseCore Component. */ +FOUNDATION_EXPORT const char *const FIRCoreVersionString; diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h new file mode 100644 index 0000000..e0dd6d6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h @@ -0,0 +1,127 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** A block that takes a BOOL and has no return value. */ +typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback); + +/** + * The entry point of Firebase SDKs. + * + * Initialize and configure FIRApp using +[FIRApp configure] + * or other customized ways as shown below. + * + * The logging system has two modes: default mode and debug mode. In default mode, only logs with + * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent + * to device. The log levels that Firebase uses are consistent with the ASL log levels. + * + * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this + * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled, + * further executions of the application will also be in debug mode. In order to return to default + * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled. + * + * It is also possible to change the default logging level in code by calling setLoggerLevel: on + * the FIRConfiguration interface. + */ +NS_SWIFT_NAME(FirebaseApp) +@interface FIRApp : NSObject + +/** + * Configures a default Firebase app. Raises an exception if any configuration step fails. The + * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched + * and before using Firebase services. This method is thread safe and contains synchronous file I/O + * (reading GoogleService-Info.plist from disk). + */ ++ (void)configure; + +/** + * Configures the default Firebase app with the provided options. The default app is named + * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread + * safe. + * + * @param options The Firebase application options used to configure the service. + */ ++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:)); + +/** + * Configures a Firebase app with the given name and options. Raises an exception if any + * configuration step fails. This method is thread safe. + * + * @param name The application's name given by the developer. The name should should only contain + Letters, Numbers and Underscore. + * @param options The Firebase application options used to configure the services. + */ +// clang-format off ++ (void)configureWithName:(NSString *)name + options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:)); +// clang-format on + +/** + * Returns the default app, or nil if the default app does not exist. + */ ++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app()); + +/** + * Returns a previously created FIRApp instance with the given name, or nil if no such app exists. + * This method is thread safe. + */ ++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:)); + +/** + * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This + * method is thread safe. + */ +@property(class, readonly, nullable) NSDictionary *allApps; + +/** + * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for + * future use. This method is thread safe. + */ +- (void)deleteApp:(FIRAppVoidBoolCallback)completion; + +/** + * FIRApp instances should not be initialized directly. Call +[FIRApp configure], + * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Gets the name of this app. + */ +@property(nonatomic, copy, readonly) NSString *name; + +/** + * Gets a copy of the options for this app. These are non-modifiable. + */ +@property(nonatomic, copy, readonly) FIROptions *options; + +/** + * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES` + * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value + * is persisted across runs of the app so that it can be set once when users have consented to + * collection. + */ +@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled) + BOOL dataCollectionDefaultEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h new file mode 100644 index 0000000..8de3b07 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This interface provides global level properties that the developer can tweak. + */ +NS_SWIFT_NAME(FirebaseConfiguration) +@interface FIRConfiguration : NSObject + +/** Returns the shared configuration object. */ +@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared); + +/** + * Sets the logging level for internal Firebase logging. Firebase will only log messages + * that are logged at or below loggerLevel. The messages are logged both to the Xcode + * console and to the device's log. Note that if an app is running from AppStore, it will + * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose) + * setting. + * + * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice. + */ +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h new file mode 100644 index 0000000..dca3aa0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note that importing GULLoggerLevel.h will lead to a non-modular header +// import error. + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, FIRLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + FIRLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + FIRLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + FIRLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + FIRLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + FIRLoggerLevelDebug = 7, + /** Minimum log level. */ + FIRLoggerLevelMin = FIRLoggerLevelError, + /** Maximum log level. */ + FIRLoggerLevelMax = FIRLoggerLevelDebug +} NS_SWIFT_NAME(FirebaseLoggerLevel); diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h new file mode 100644 index 0000000..87a01dd --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h @@ -0,0 +1,116 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class provides constant fields of Google APIs. + */ +NS_SWIFT_NAME(FirebaseOptions) +@interface FIROptions : NSObject + +/** + * Returns the default options. The first time this is called it synchronously reads + * GoogleService-Info.plist from disk. + */ ++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions()); + +/** + * An iOS API key used for authenticating requests from your app, e.g. + * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers. + */ +@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey); + +/** + * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set + * manually or in a plist. + */ +@property(nonatomic, copy) NSString *bundleID; + +/** + * The OAuth2 client ID for iOS application used to authenticate Google users, for example + * @"12345.apps.googleusercontent.com", used for signing in with Google. + */ +@property(nonatomic, copy, nullable) NSString *clientID; + +/** + * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics. + */ +@property(nonatomic, copy, nullable) NSString *trackingID; + +/** + * The Project Number from the Google Developer's console, for example @"012345678901", used to + * configure Google Cloud Messaging. + */ +@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID); + +/** + * The Project ID from the Firebase console, for example @"abc-xyz-123". + */ +@property(nonatomic, copy, nullable) NSString *projectID; + +/** + * The Android client ID used in Google AppInvite when an iOS app has its Android version, for + * example @"12345.apps.googleusercontent.com". + */ +@property(nonatomic, copy, nullable) NSString *androidClientID; + +/** + * The Google App ID that is used to uniquely identify an instance of an app. + */ +@property(nonatomic, copy) NSString *googleAppID; + +/** + * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com". + */ +@property(nonatomic, copy, nullable) NSString *databaseURL; + +/** + * The URL scheme used to set up Durable Deep Link service. + */ +@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme; + +/** + * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com". + */ +@property(nonatomic, copy, nullable) NSString *storageBucket; + +/** + * Initializes a customized instance of FIROptions from the file at the given plist file path. This + * will read the file synchronously from disk. + * For example, + * NSString *filePath = + * [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]; + * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; + * Returns nil if the plist file does not exist or is invalid. + */ +- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath; + +/** + * Initializes a customized instance of FIROptions with required fields. Use the mutable properties + * to modify fields for configuring specific services. + */ +// clang-format off +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + GCMSenderID:(NSString *)GCMSenderID + NS_SWIFT_NAME(init(googleAppID:gcmSenderID:)); +// clang-format on + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h new file mode 100644 index 0000000..95119ae --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/LICENSE b/PRODUCTNAME/app/Pods/FirebaseCore/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PRODUCTNAME/app/Pods/FirebaseCore/README.md b/PRODUCTNAME/app/Pods/FirebaseCore/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseCore/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h new file mode 100644 index 0000000..fadde02 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h @@ -0,0 +1,160 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// The format of the debug code will show in the log as: e.g. +// for code 1000, it will show as I-IID001000. +typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) { + // DO NOT USE 2000, 2002. + kFIRInstanceIDMessageCodeFIRApp000 = 1000, // I-IID001000 + kFIRInstanceIDMessageCodeFIRApp001 = 1001, + kFIRInstanceIDMessageCodeFIRApp002 = 1002, + kFIRInstanceIDMessageCodeInternal001 = 2001, + kFIRInstanceIDMessageCodeInternal002 = 2002, + // FIRInstanceID.m + // DO NOT USE 4000. + kFIRInstanceIDMessageCodeInstanceID000 = 3000, + kFIRInstanceIDMessageCodeInstanceID001 = 3001, + kFIRInstanceIDMessageCodeInstanceID002 = 3002, + kFIRInstanceIDMessageCodeInstanceID003 = 3003, + kFIRInstanceIDMessageCodeInstanceID004 = 3004, + kFIRInstanceIDMessageCodeInstanceID005 = 3005, + kFIRInstanceIDMessageCodeInstanceID006 = 3006, + kFIRInstanceIDMessageCodeInstanceID007 = 3007, + kFIRInstanceIDMessageCodeInstanceID008 = 3008, + kFIRInstanceIDMessageCodeInstanceID009 = 3009, + kFIRInstanceIDMessageCodeInstanceID010 = 3010, + kFIRInstanceIDMessageCodeInstanceID011 = 3011, + kFIRInstanceIDMessageCodeInstanceID012 = 3012, + kFIRInstanceIDMessageCodeInstanceID013 = 3013, + kFIRInstanceIDMessageCodeInstanceID014 = 3014, + kFIRInstanceIDMessageCodeInstanceID015 = 3015, + kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016, + // FIRInstanceIDAuthService.m + kFIRInstanceIDMessageCodeAuthService000 = 5000, + kFIRInstanceIDMessageCodeAuthService001 = 5001, + kFIRInstanceIDMessageCodeAuthService002 = 5002, + kFIRInstanceIDMessageCodeAuthService003 = 5003, + kFIRInstanceIDMessageCodeAuthService004 = 5004, + kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress = 5004, + + // FIRInstanceIDBackupExcludedPlist.m + kFIRInstanceIDMessageCodeBackupExcludedPlist000 = 6000, + kFIRInstanceIDMessageCodeBackupExcludedPlist001 = 6001, + kFIRInstanceIDMessageCodeBackupExcludedPlist002 = 6002, + kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum = 6003, + // FIRInstanceIDCheckinService.m + kFIRInstanceIDMessageCodeService000 = 7000, + kFIRInstanceIDMessageCodeService001 = 7001, + kFIRInstanceIDMessageCodeService002 = 7002, + kFIRInstanceIDMessageCodeService003 = 7003, + kFIRInstanceIDMessageCodeService004 = 7004, + kFIRInstanceIDMessageCodeService005 = 7005, + kFIRInstanceIDMessageCodeService006 = 7006, + kFIRIntsanceIDInvalidNetworkSession = 7007, + // FIRInstanceIDCheckinStore.m + // DO NOT USE 8002, 8004 - 8008 + kFIRInstanceIDMessageCodeCheckinStore000 = 8000, + kFIRInstanceIDMessageCodeCheckinStore001 = 8001, + kFIRInstanceIDMessageCodeCheckinStore003 = 8003, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted = 8009, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved = 8010, + // FIRInstanceIDKeyPair.m + // DO NOT USE 9001, 9003 + kFIRInstanceIDMessageCodeKeyPair000 = 9000, + kFIRInstanceIDMessageCodeKeyPair002 = 9002, + kFIRInstanceIDMessageCodeKeyPairMigrationError = 9004, + kFIRInstanceIDMessageCodeKeyPairMigrationSuccess = 9005, + kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair = 9006, + + // FIRInstanceIDKeyPairStore.m + kFIRInstanceIDMessageCodeKeyPairStore000 = 10000, + kFIRInstanceIDMessageCodeKeyPairStore001 = 10001, + kFIRInstanceIDMessageCodeKeyPairStore002 = 10002, + kFIRInstanceIDMessageCodeKeyPairStore003 = 10003, + kFIRInstanceIDMessageCodeKeyPairStore004 = 10004, + kFIRInstanceIDMessageCodeKeyPairStore005 = 10005, + kFIRInstanceIDMessageCodeKeyPairStore006 = 10006, + kFIRInstanceIDMessageCodeKeyPairStore007 = 10007, + kFIRInstanceIDMessageCodeKeyPairStore008 = 10008, + kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair = 10009, + // FIRInstanceIDKeyPairUtilities.m + kFIRInstanceIDMessageCodeKeyPairUtilities000 = 11000, + kFIRInstanceIDMessageCodeKeyPairUtilities001 = 11001, + kFIRInstanceIDMessageCodeKeyPairUtilitiesFirstConcatenateParamNil = 11002, + + // DO NOT USE 12000 - 12014 + + // FIRInstanceIDStore.m + // DO NOT USE 13004, 13005, 13007, 13008, 13010, 13011, 13013, 13014 + kFIRInstanceIDMessageCodeStore000 = 13000, + kFIRInstanceIDMessageCodeStore001 = 13001, + kFIRInstanceIDMessageCodeStore002 = 13002, + kFIRInstanceIDMessageCodeStore003 = 13003, + kFIRInstanceIDMessageCodeStore006 = 13006, + kFIRInstanceIDMessageCodeStore009 = 13009, + kFIRInstanceIDMessageCodeStore012 = 13012, + // FIRInstanceIDTokenManager.m + // DO NOT USE 14002, 14005 + kFIRInstanceIDMessageCodeTokenManager000 = 14000, + kFIRInstanceIDMessageCodeTokenManager001 = 14001, + kFIRInstanceIDMessageCodeTokenManager003 = 14003, + kFIRInstanceIDMessageCodeTokenManager004 = 14004, + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset = 14006, + kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset = 14007, + kFIRInstanceIDMessageCodeTokenManagerSavedAppVersion = 14008, + kFIRInstanceIDMessageCodeTokenManagerErrorInvalidatingAllTokens = 14009, + kFIRInstanceIDMessageCodeTokenManagerAPNSChanged = 14010, + kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated = 14011, + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken = 14012, + // FIRInstanceIDTokenStore.m + // DO NOT USE 15002 - 15013 + kFIRInstanceIDMessageCodeTokenStore000 = 15000, + kFIRInstanceIDMessageCodeTokenStore001 = 15001, + kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo = 15015, + + // DO NOT USE 16000, 18004 + + // FIRInstanceIDUtilities.m + kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier = 18000, + kFIRInstanceIDMessageCodeUtilitiesAppEnvironmentUtilNotAvailable = 18001, + kFIRInstanceIDMessageCodeUtilitiesCannotGetHardwareModel = 18002, + kFIRInstanceIDMessageCodeUtilitiesCannotGetSystemVersion = 18003, + // FIRInstanceIDTokenOperation.m + kFIRInstanceIDMessageCodeTokenOperationFailedToSignParams = 19000, + // FIRInstanceIDTokenFetchOperation.m + // DO NOT USE 20004, 20005 + kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest = 20000, + kFIRInstanceIDMessageCodeTokenFetchOperationRequestError = 20001, + kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse = 20002, + kFIRInstanceIDMessageCodeTokenFetchOperationBadTokenStructure = 20003, + // FIRInstanceIDTokenDeleteOperation.m + kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest = 21000, + kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError = 21001, + kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse = 21002, + // FIRInstanceIDTokenInfo.m + kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo = 22000, + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged = 22001, + kFIRInstanceIDMessageCodeTokenInfoLocaleChanged = 22002, + // FIRInstanceIDKeychain.m + kFIRInstanceIDKeychainReadItemError = 23000, + kFIRInstanceIDKeychainAddItemError = 23001, + kFIRInstanceIDKeychainDeleteItemError = 23002, + kFIRInstanceIDKeychainCreateKeyPairError = 23003, + kFIRInstanceIDKeychainUpdateItemError = 23004, + +}; diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h new file mode 100644 index 0000000..3e3ec17 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import "FIRInstanceIDCheckinService.h" + +/** + * Internal API used by Firebase SDK teams by calling in reflection or internal teams. + */ +// TODO(chliangGoogle) Rename this to Internal. +@interface FIRInstanceID (Private) + +/** + * Return the cached checkin preferences on the disk. This is used internally only by Messaging. + * + * @return The cached checkin preferences on the client. + */ +- (nullable FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Fetches checkin info for the app. If the app has valid cached checkin preferences + * they are returned instead of making a network request. + * + * @param handler The completion handler to invoke once the request has completed. + */ +- (void)fetchCheckinInfoWithHandler:(nullable FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Get the InstanceID for the app. If an ID was created before and cached + * successfully we will return that ID. If no cached ID exists we create + * a new ID, cache it and return that. + * + * This is a blocking call and should not really be called on the main thread. + * + * @param error The error object that represents the error while trying to + * retrieve the instance id. + * + * @return The InstanceID for the app. + */ +- (nullable NSString *)appInstanceID:(NSError *_Nullable *_Nullable)error; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m new file mode 100644 index 0000000..61d43a4 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID+Private.h" + +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDKeyPairStore.h" +#import "FIRInstanceIDTokenManager.h" + +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readonly, strong) FIRInstanceIDKeyPairStore *keyPairStore; + +@end + +@implementation FIRInstanceID (Private) + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.tokenManager.authService checkinPreferences]; +} + +// This method just wraps our pre-configured auth service to make the request. +// This method is only needed by first-party users, like Remote Config. +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler { + [self.tokenManager.authService fetchCheckinInfoWithHandler:handler]; +} + +- (NSString *)appInstanceID:(NSError **)error { + return [self.keyPairStore appIdentityWithError:error]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m new file mode 100644 index 0000000..e5b39e3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m @@ -0,0 +1,1186 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import +#import +#import +#import +#import +#import +#import "FIRInstanceID+Private.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCombinedHandler.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPairStore.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenManager.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +// Public constants +NSString *const kFIRInstanceIDScopeFirebaseMessaging = @"fcm"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName kFIRInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +#else +NSString *const kFIRInstanceIDTokenRefreshNotification = @"com.firebase.iid.notif.refresh-token"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRInstanceIDInvalidNilHandlerError = @"Invalid nil handler."; + +// Private constants +int64_t const kMaxRetryIntervalForDefaultTokenInSeconds = 20 * 60; // 20 minutes +int64_t const kMinRetryIntervalForDefaultTokenInSeconds = 10; // 10 seconds +// we retry only a max 5 times. +// TODO(chliangGoogle): If we still fail we should listen for the network change notification +// since GCM would have started Reachability. We only start retrying after we see a configuration +// change. +NSInteger const kMaxRetryCountForDefaultToken = 5; + +static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment"; +static NSString *const kAPSEnvironmentDevelopmentValue = @"development"; +/// FIRMessaging selector that returns the current FIRMessaging auto init +/// enabled flag. +static NSString *const kFIRInstanceIDFCMSelectorAutoInitEnabled = @"isAutoInitEnabled"; +static NSString *const kFIRInstanceIDFCMSelectorInstance = @"messaging"; + +static NSString *const kFIRInstanceIDAPNSTokenType = @"APNSTokenType"; +static NSString *const kFIRIIDAppReadyToConfigureSDKNotification = + @"FIRAppReadyToConfigureSDKNotification"; +static NSString *const kFIRIIDAppNameKey = @"FIRAppNameKey"; +static NSString *const kFIRIIDErrorDomain = @"com.firebase.instanceid"; +static NSString *const kFIRIIDServiceInstanceID = @"InstanceID"; + +static NSInteger const kFIRIIDErrorCodeInstanceIDFailed = -121; + +typedef void (^FIRInstanceIDKeyPairHandler)(FIRInstanceIDKeyPair *keyPair, NSError *error); + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * InstanceID will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * This must match FIRMessagingAPNSTokenType in FIRMessaging.h + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) { + /// Unknown token type. + FIRInstanceIDAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRInstanceIDAPNSTokenTypeSandbox, + /// Production token type. + FIRInstanceIDAPNSTokenTypeProd, +} NS_SWIFT_NAME(InstanceIDAPNSTokenType); + +@interface FIRInstanceIDResult () +@property(nonatomic, readwrite, copy) NSString *instanceID; +@property(nonatomic, readwrite, copy) NSString *token; +@end + +@interface FIRInstanceID () + +// FIRApp configuration objects. +@property(nonatomic, readwrite, copy) NSString *fcmSenderID; +@property(nonatomic, readwrite, copy) NSString *firebaseAppID; + +// Raw APNS token data +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; + +@property(nonatomic, readwrite) FIRInstanceIDAPNSTokenType apnsTokenType; +// String-based, internal representation of APNS token +@property(nonatomic, readwrite, copy) NSString *APNSTupleString; +// Token fetched from the server automatically for the default app. +@property(nonatomic, readwrite, copy) NSString *defaultFCMToken; + +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPairStore *keyPairStore; + +// backoff and retry for default token +@property(nonatomic, readwrite, assign) NSInteger retryCountForDefaultToken; +@property(atomic, strong, nullable) + FIRInstanceIDCombinedHandler *defaultTokenFetchHandler; + +@end + +// InstanceID doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRInstanceIDInstanceProvider +@end + +@interface FIRInstanceID () +@end + +@implementation FIRInstanceIDResult +- (id)copyWithZone:(NSZone *)zone { + FIRInstanceIDResult *result = [[[self class] allocWithZone:zone] init]; + result.instanceID = self.instanceID; + result.token = self.token; + return result; +} +@end + +@implementation FIRInstanceID + +// File static to support InstanceID tests that call [FIRInstanceID instanceID] after +// [FIRInstanceID instanceIDForTests]. +static FIRInstanceID *gInstanceID; + ++ (instancetype)instanceID { + // If the static instance was created, return it. This should only be set in tests and we should + // eventually use proper dependency injection for a better test structure. + if (gInstanceID != nil) { + return gInstanceID; + } + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + FIRInstanceID *instanceID = + (FIRInstanceID *)FIR_COMPONENT(FIRInstanceIDInstanceProvider, defaultApp.container); + return instanceID; +} + +- (instancetype)initPrivately { + self = [super init]; + if (self != nil) { + // Use automatic detection of sandbox, unless otherwise set by developer + _apnsTokenType = FIRInstanceIDAPNSTokenTypeUnknown; + } + return self; +} + ++ (FIRInstanceID *)instanceIDForTests { + gInstanceID = [[FIRInstanceID alloc] initPrivately]; + [gInstanceID start]; + return gInstanceID; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Tokens + +- (NSString *)token { + if (!self.fcmSenderID.length) { + return nil; + } + + NSString *cachedToken = [self cachedTokenIfAvailable]; + + if (cachedToken) { + return cachedToken; + } else { + // If we've never had a cached default token, we should fetch one because unrelatedly, + // this request will help us determine whether the locally-generated Instance ID keypair is not + // unique, and therefore generate a new one. + [self defaultTokenWithHandler:nil]; + return nil; + } +} + +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler { + FIRInstanceID_WEAKIFY(self); + [self getIDWithHandler:^(NSString *identity, NSError *error) { + FIRInstanceID_STRONGIFY(self); + // This is in main queue already + if (error) { + if (handler) { + handler(nil, error); + } + return; + } + FIRInstanceIDResult *result = [[FIRInstanceIDResult alloc] init]; + result.instanceID = identity; + NSString *cachedToken = [self cachedTokenIfAvailable]; + if (cachedToken) { + if (handler) { + result.token = cachedToken; + handler(result, nil); + } + // If no handler, simply return since client has generated iid and token. + return; + } + [self defaultTokenWithHandler:^(NSString *_Nullable token, NSError *_Nullable error) { + if (handler) { + if (error) { + handler(nil, error); + return; + } + result.token = token; + handler(result, nil); + } + }]; + }]; +} + +- (NSString *)cachedTokenIfAvailable { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope]; + return cachedTokenInfo.token; +} + +- (void)setDefaultFCMToken:(NSString *)defaultFCMToken { + if (_defaultFCMToken && defaultFCMToken && [defaultFCMToken isEqualToString:_defaultFCMToken]) { + return; + } + + _defaultFCMToken = defaultFCMToken; + + // Sending this notification out will ensure that FIRMessaging has the updated + // default FCM token. + NSNotification *internalDefaultTokenNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenNotification + object:_defaultFCMToken]; + [[NSNotificationQueue defaultQueue] enqueueNotification:internalDefaultTokenNotification + postingStyle:NSPostASAP]; +} + +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + _FIRInstanceIDDevAssert(handler != nil && [authorizedEntity length] && [scope length], + @"Invalid authorizedEntity or scope to new token"); + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID000, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + NSMutableDictionary *tokenOptions = [NSMutableDictionary dictionary]; + if (options.count) { + [tokenOptions addEntriesFromDictionary:options]; + } + + NSString *APNSKey = kFIRInstanceIDTokenOptionsAPNSKey; + NSString *serverTypeKey = kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + + if (tokenOptions[APNSKey] != nil && tokenOptions[serverTypeKey] == nil) { + // APNS key was given, but server type is missing. Supply the server type with automatic + // checking. This can happen when the token is requested from FCM, which does not include a + // server type during its request. + tokenOptions[serverTypeKey] = @([self isSandboxApp]); + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + if (FIRInstanceIDIsValidGCMScope(scope) && !tokenOptions[APNSKey]) { + errorCode = kFIRInstanceIDErrorCodeMissingAPNSToken; + } else if (FIRInstanceIDIsValidGCMScope(scope) && + ![tokenOptions[APNSKey] isKindOfClass:[NSData class]]) { + errorCode = kFIRInstanceIDErrorCodeInvalidRequest; + } else if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.keyPairStore) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDTokenHandler newHandler = ^(NSString *token, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(token, error); + }); + }; + + if (errorCode != noError) { + newHandler(nil, [NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + // TODO(chliangGoogle): Add some validation logic that the APNs token data and sandbox value are + // supplied in the valid format (NSData and BOOL, respectively). + + // Add internal options + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(nil, error); + return; + } + + // Only use the token in the cache if the APNSInfo matches what the request's options has. + // It's possible for the request to be with a newer APNs device token, which should be + // honored. + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; + if (cachedTokenInfo) { + // Ensure that the cached token matches APNs data before returning it. + FIRInstanceIDAPNSInfo *optionsAPNSInfo = + [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions]; + // If either the APNs info is missing in both, or if they are an exact match, then we can + // use this cached token. + if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) || + [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) { + newHandler(cachedTokenInfo.token, nil); + return; + } + } + + FIRInstanceID_WEAKIFY(self); + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(nil, newError); + + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:[authorizedEntity copy] + scope:[scope copy] + keyPair:keyPair + options:tokenOptions + handler:newHandler]; + } + }]; + }]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler { + _FIRInstanceIDDevAssert(handler != nil && [authorizedEntity length] && [scope length], + @"Invalid authorizedEntity or scope to delete token"); + + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID001, + kFIRInstanceIDInvalidNilHandlerError); + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + + if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.keyPairStore) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) { + // If a default token is deleted successfully, reset the defaultFCMToken too. + if (!error && [authorizedEntity isEqualToString:self.fcmSenderID] && + [scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + self.defaultFCMToken = nil; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (errorCode != noError) { + newHandler([NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(newError); + + } else { + [self.tokenManager deleteTokenWithAuthorizedEntity:authorizedEntity + scope:scope + keyPair:keyPair + handler:newHandler]; + } + }]; + }]; +} + +- (void)asyncLoadKeyPairWithHandler:(FIRInstanceIDKeyPairHandler)handler { + FIRInstanceID_WEAKIFY(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + FIRInstanceID_STRONGIFY(self); + + NSError *error = nil; + FIRInstanceIDKeyPair *keyPair = [self.keyPairStore loadKeyPairWithError:&error]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID002, + @"Failed to retreieve keyPair %@", error); + if (handler) { + handler(nil, error); + } + } else if (!keyPair && !error) { + if (handler) { + handler(nil, + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]); + } + } else { + if (handler) { + handler(keyPair, nil); + } + } + }); + }); +} + +#pragma mark - Identity + +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler { + _FIRInstanceIDDevAssert(handler, @"Invalid nil handler to getIdentity"); + + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID003, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSString *, NSError *) = ^(NSString *identity, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(identity, error); + }); + }; + + if (!self.keyPairStore) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidStart]; + callHandlerOnMainThread(nil, error); + return; + } + + FIRInstanceID_WEAKIFY(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + FIRInstanceID_STRONGIFY(self); + NSError *error; + NSString *appIdentity = [self.keyPairStore appIdentityWithError:&error]; + // When getID is explicitly called, trigger getToken to make sure token always exists. + // This is to avoid ID conflict (ID is not checked for conflict until we generate a token) + if (appIdentity) { + [self token]; + } + callHandlerOnMainThread(appIdentity, error); + }); +} + +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler { + _FIRInstanceIDDevAssert(handler, @"Invalid nil handler to delete Identity"); + + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID004, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSError *) = ^(NSError *error) { + if ([NSThread isMainThread]) { + handler(error); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (!self.keyPairStore) { + FIRInstanceIDErrorCode error = kFIRInstanceIDErrorCodeInvalidStart; + callHandlerOnMainThread([NSError errorWithFIRInstanceIDErrorCode:error]); + return; + } + + FIRInstanceID_WEAKIFY(self); + void (^deleteTokensHandler)(NSError *) = ^void(NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + callHandlerOnMainThread(error); + return; + } + [self deleteIdentityWithHandler:^(NSError *error) { + callHandlerOnMainThread(error); + }]; + }; + + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + callHandlerOnMainThread(newError); + } else { + [self.tokenManager deleteAllTokensWithKeyPair:keyPair handler:deleteTokensHandler]; + } + }]; +} + +- (void)notifyIdentityReset { + [self deleteIdentityWithHandler:nil]; +} + +// Delete all the local cache checkin, IID and token. +- (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler { + // Delete tokens. + [self.tokenManager deleteAllTokensLocallyWithHandler:^(NSError *deleteTokenError) { + // Reset FCM token. + self.defaultFCMToken = nil; + if (deleteTokenError) { + if (handler) { + handler(deleteTokenError); + } + return; + } + + // Delete Instance ID. + [self.keyPairStore + deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType + handler:^(NSError *error) { + NSError *deletePlistError; + [self.keyPairStore + removeKeyPairCreationTimePlistWithError:&deletePlistError]; + if (error || deletePlistError) { + if (handler) { + // Prefer to use the delete Instance ID error. + error = [NSError + errorWithFIRInstanceIDErrorCode: + kFIRInstanceIDErrorCodeUnknown + userInfo:@{ + NSUnderlyingErrorKey : error + ? error + : deletePlistError + }]; + handler(error); + } + return; + } + // Delete checkin. + [self.tokenManager.authService + resetCheckinWithHandler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + // Only request new token if FCM auto initialization is + // enabled. + if ([self isFCMAutoInitEnabled]) { + // Deletion succeeds! Requesting new checkin, IID and token. + // TODO(chliangGoogle) see if dispatch_after is necessary + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(0.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self defaultTokenWithHandler:nil]; + }); + } + if (handler) { + handler(nil); + } + }]; + }]; + }]; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-iid" + withVersion:FIRInstanceIDCurrentLibraryVersion()]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // Ensure it's cached so it returns the same instance every time instanceID is called. + *isCacheable = YES; + FIRInstanceID *instanceID = [[FIRInstanceID alloc] initPrivately]; + [instanceID start]; + return instanceID; + }; + FIRComponent *instanceIDProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstanceIDInstanceProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; + return @[ instanceIDProvider ]; +} + ++ (void)configureWithApp:(FIRApp *)app { + if (!app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeFIRApp002, + @"Firebase Instance ID only works with the default app."); + return; + } + [[FIRInstanceID instanceID] configureInstanceIDWithOptions:app.options app:app]; +} + +- (void)configureInstanceIDWithOptions:(FIROptions *)options app:(FIRApp *)firApp { + NSString *GCMSenderID = options.GCMSenderID; + if (!GCMSenderID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeFIRApp000, + @"Firebase not set up correctly, nil or empty senderID."); + [FIRInstanceID exitWithReason:@"GCM_SENDER_ID must not be nil or empty." forFirebaseApp:firApp]; + return; + } + + self.fcmSenderID = GCMSenderID; + self.firebaseAppID = firApp.options.googleAppID; + + // FCM generates a FCM token during app start for sending push notification to device. + // This is not needed for app extension. + if (![GULAppEnvironmentUtil isAppExtension]) { + [self didCompleteConfigure]; + } +} + ++ (NSError *)configureErrorWithReason:(nonnull NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", kFIRIIDServiceInstanceID]; + if (!reason.length) { + reason = @"Unknown reason"; + } + + NSDictionary *userInfo = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + + return [NSError errorWithDomain:kFIRIIDErrorDomain + code:kFIRIIDErrorCodeInstanceIDFailed + userInfo:userInfo]; +} + +// If the firebaseApp is available we should send logs for the error through it before +// raising an exception. ++ (void)exitWithReason:(nonnull NSString *)reason forFirebaseApp:(FIRApp *)firebaseApp { + [firebaseApp sendLogsWithServiceName:kFIRIIDServiceInstanceID + version:FIRInstanceIDCurrentLibraryVersion() + error:[self configureErrorWithReason:reason]]; + + [NSException raise:kFIRIIDErrorDomain + format:@"Could not configure Firebase InstanceID. %@", reason]; +} + +// This is used to start any operations when we receive FirebaseSDK setup notification +// from FIRCore. +- (void)didCompleteConfigure { + NSString *cachedToken = [self cachedTokenIfAvailable]; + // When there is a cached token, do the token refresh. + if (cachedToken) { + // Clean up expired tokens by checking the token refresh policy. + if ([self.tokenManager checkForTokenRefreshPolicy]) { + // Default token is expired, fetch default token from server. + [self defaultTokenWithHandler:nil]; + } + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } else if ([self isFCMAutoInitEnabled]) { + // When there is no cached token, must check auto init is enabled. + // If it's disabled, don't initiate token generation/refresh. + // If no cache token and auto init is enabled, fetch a token from server. + [self defaultTokenWithHandler:nil]; + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } + // ONLY checkin when auto data collection is turned on. + if ([self isFCMAutoInitEnabled]) { + [self.tokenManager.authService scheduleCheckin:YES]; + } +} + +- (BOOL)isFCMAutoInitEnabled { + Class messagingClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + // Firebase Messaging is not installed, auto init should be disabled since it's for FCM. + if (!messagingClass) { + return NO; + } + + // Messaging doesn't have the singleton method, auto init should be enabled since FCM exists. + SEL instanceSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorInstance); + if (![messagingClass respondsToSelector:instanceSelector]) { + return YES; + } + + // Get FIRMessaging shared instance. + IMP messagingInstanceIMP = [messagingClass methodForSelector:instanceSelector]; + id (*getMessagingInstance)(id, SEL) = (void *)messagingInstanceIMP; + id messagingInstance = getMessagingInstance(messagingClass, instanceSelector); + + // Messaging doesn't have the property, auto init should be enabled since FCM exists. + SEL autoInitSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorAutoInitEnabled); + if (![messagingInstance respondsToSelector:autoInitSelector]) { + return YES; + } + + // Get autoInitEnabled method. + IMP isAutoInitEnabledIMP = [messagingInstance methodForSelector:autoInitSelector]; + BOOL (*isAutoInitEnabled)(id, SEL) = (BOOL(*)(id, SEL))isAutoInitEnabledIMP; + + // Check FCM's isAutoInitEnabled property. + return isAutoInitEnabled(messagingInstance, autoInitSelector); +} + +// Actually makes InstanceID instantiate both the IID and Token-related subsystems. +- (void)start { + if (![FIRInstanceIDStore hasSubDirectory:kFIRInstanceIDSubDirectoryName]) { + [FIRInstanceIDStore createSubDirectory:kFIRInstanceIDSubDirectoryName]; + } + + [self setupTokenManager]; + [self setupKeyPairManager]; + [self setupNotificationListeners]; +} + +// Creates the token manager, which is used for fetching, caching, and retrieving tokens. +- (void)setupTokenManager { + self.tokenManager = [[FIRInstanceIDTokenManager alloc] init]; +} + +// Creates a key pair manager, which stores the public/private keys needed to generate an +// application instance ID. +- (void)setupKeyPairManager { + self.keyPairStore = [[FIRInstanceIDKeyPairStore alloc] init]; + if ([self.keyPairStore invalidateKeyPairsIfNeeded]) { + // Reset tokens right away when keypair is deleted, otherwise async call can make first query + // of token happens before reset old tokens during app start. + // TODO(chliangGoogle): Delete all tokens on server too, using + // deleteAllTokensWithKeyPair:handler:. This requires actually retrieving the invalid keypair + // from Keychain, which is something that the key pair store does not currently do. + [self.tokenManager deleteAllTokensLocallyWithHandler:nil]; + } +} + +- (void)setupNotificationListeners { + // To prevent double notifications remove observer from all events during setup. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + [center addObserver:self + selector:@selector(notifyIdentityReset) + name:kFIRInstanceIDIdentityInvalidatedNotification + object:nil]; + [center addObserver:self + selector:@selector(notifyAPNSTokenIsSet:) + name:kFIRInstanceIDAPNSTokenNotification + object:nil]; +} + +#pragma mark - Private Helpers +/// Maximum retry count to fetch the default token. ++ (int64_t)maxRetryCountForDefaultToken { + return kMaxRetryCountForDefaultToken; +} + +/// Minimum interval in seconds between retries to fetch the default token. ++ (int64_t)minIntervalForDefaultTokenRetry { + return kMinRetryIntervalForDefaultTokenInSeconds; +} + +/// Maximum retry interval between retries to fetch default token. ++ (int64_t)maxRetryIntervalForDefaultTokenInSeconds { + return kMaxRetryIntervalForDefaultTokenInSeconds; +} + +- (NSInteger)retryIntervalToFetchDefaultToken { + if (self.retryCountForDefaultToken >= [[self class] maxRetryCountForDefaultToken]) { + return (NSInteger)[[self class] maxRetryIntervalForDefaultTokenInSeconds]; + } + // exponential backoff with a fixed initial retry time + // 11s, 22s, 44s, 88s ... + int64_t minInterval = [[self class] minIntervalForDefaultTokenRetry]; + return (NSInteger)MIN( + (1 << self.retryCountForDefaultToken) + minInterval * self.retryCountForDefaultToken, + kMaxRetryIntervalForDefaultTokenInSeconds); +} + +- (void)defaultTokenWithHandler:(nullable FIRInstanceIDTokenHandler)aHandler { + [self defaultTokenWithRetry:NO handler:aHandler]; +} + +/** + * @param retry Indicates if the method is called to perform a retry after a failed attempt. + * If `YES`, then actual token request will be performed even if `self.defaultTokenFetchHandler != + * nil` + */ +- (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHandler)aHandler { + BOOL shouldPerformRequest = retry || self.defaultTokenFetchHandler == nil; + + if (!self.defaultTokenFetchHandler) { + self.defaultTokenFetchHandler = [[FIRInstanceIDCombinedHandler alloc] init]; + } + + if (aHandler) { + [self.defaultTokenFetchHandler addHandler:aHandler]; + } + + if (!shouldPerformRequest) { + return; + } + + NSDictionary *instanceIDOptions = @{}; + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging && self.apnsTokenData) { + BOOL isSandboxApp = (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + instanceIDOptions = @{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp), + }; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenHandler newHandler = ^void(NSString *token, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID009, + @"Failed to fetch default token %@", error); + + // This notification can be sent multiple times since we can't guarantee success at any point + // of time. + NSNotification *tokenFetchFailNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenFailNotification + object:[error copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenFetchFailNotification + postingStyle:NSPostASAP]; + + self.retryCountForDefaultToken = (NSInteger)MIN(self.retryCountForDefaultToken + 1, + [[self class] maxRetryCountForDefaultToken]); + + // Do not retry beyond the maximum limit. + if (self.retryCountForDefaultToken < [[self class] maxRetryCountForDefaultToken]) { + NSInteger retryInterval = [self retryIntervalToFetchDefaultToken]; + [self retryGetDefaultTokenAfter:retryInterval]; + } else { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID007, + @"Failed to retrieve the default FCM token after %ld retries", + (long)self.retryCountForDefaultToken); + [self performDefaultTokenHandlerWithToken:nil error:error]; + } + } else { + // If somebody updated IID with APNS token while our initial request did not have it + // set we need to update it on the server. + NSData *deviceTokenInRequest = instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSKey]; + BOOL isSandboxInRequest = + [instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey] boolValue]; + // Note that APNSTupleStringInRequest will be nil if deviceTokenInRequest is nil + NSString *APNSTupleStringInRequest = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + deviceTokenInRequest, isSandboxInRequest); + // If the APNs value either remained nil, or was the same non-nil value, the APNs value + // did not change. + BOOL APNSRemainedSameDuringFetch = + (self.APNSTupleString == nil && APNSTupleStringInRequest == nil) || + ([self.APNSTupleString isEqualToString:APNSTupleStringInRequest]); + if (!APNSRemainedSameDuringFetch && hasFirebaseMessaging) { + // APNs value did change mid-fetch, so the token should be re-fetched with the current APNs + // value. + [self retryGetDefaultTokenAfter:0]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeRefetchingTokenForAPNS, + @"Received APNS token while fetching default token. " + @"Refetching default token."); + // Do not notify and handle completion handler since this is a retry. + // Simply return. + return; + } else { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeInstanceID010, + @"Successfully fetched default token."); + } + // Post the required notifications if somebody is waiting. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@", + token); + NSString *previousFCMToken = self.defaultFCMToken; + self.defaultFCMToken = token; + + // Only notify of token refresh if we have a new valid token that's different than before + if (self.defaultFCMToken.length && ![self.defaultFCMToken isEqualToString:previousFCMToken]) { + NSNotification *tokenRefreshNotification = + [NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification + object:[self.defaultFCMToken copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification + postingStyle:NSPostASAP]; + + [self performDefaultTokenHandlerWithToken:token error:nil]; + } + } + }; + + [self tokenWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope + options:instanceIDOptions + handler:newHandler]; +} + +/** + * + */ +- (void)performDefaultTokenHandlerWithToken:(NSString *)token error:(NSError *)error { + if (!self.defaultTokenFetchHandler) { + return; + } + + [self.defaultTokenFetchHandler combinedHandler](token, error); + self.defaultTokenFetchHandler = nil; +} + +- (void)retryGetDefaultTokenAfter:(NSTimeInterval)retryInterval { + FIRInstanceID_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + // Pass nil: no new handlers to be added, currently existing handlers + // will be called + [self defaultTokenWithRetry:YES handler:nil]; + }); +} + +#pragma mark - APNS Token +// This should only be triggered from FCM. +- (void)notifyAPNSTokenIsSet:(NSNotification *)notification { + NSData *token = notification.object; + if (!token || ![token isKindOfClass:[NSData class]]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal002, @"Invalid APNS token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSInteger type = [notification.userInfo[kFIRInstanceIDAPNSTokenType] integerValue]; + + // The APNS token is being added, or has changed (rare) + if ([self.apnsTokenData isEqualToData:token]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID011, + @"Trying to reset APNS token to the same value. Will return"); + return; + } + // Use this token type for when we have to automatically fetch tokens in the future + self.apnsTokenType = type; + BOOL isSandboxApp = (type == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + self.apnsTokenData = [token copy]; + self.APNSTupleString = FIRInstanceIDAPNSTupleStringForTokenAndServerType(token, isSandboxApp); + + // Pro-actively invalidate the default token, if the APNs change makes it + // invalid. Previously, we invalidated just before fetching the token. + NSArray *invalidatedTokens = + [self.tokenManager updateTokensToAPNSDeviceToken:self.apnsTokenData isSandbox:isSandboxApp]; + + // Re-fetch any invalidated tokens automatically, this time with the current APNs token, so that + // they are up-to-date. + if (invalidatedTokens.count > 0) { + FIRInstanceID_WEAKIFY(self); + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + NSMutableDictionary *tokenOptions = [@{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp) + } mutableCopy]; + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + for (FIRInstanceIDTokenInfo *tokenInfo in invalidatedTokens) { + if ([tokenInfo.token isEqualToString:self.defaultFCMToken]) { + // We will perform a special fetch for the default FCM token, so that the delegate methods + // are called. For all others, we will do an internal re-fetch. + [self defaultTokenWithHandler:nil]; + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope + keyPair:keyPair + options:tokenOptions + handler:^(NSString *_Nullable token, + NSError *_Nullable error){ + + }]; + } + } + }]; + } +} + +- (BOOL)isSandboxApp { + static BOOL isSandboxApp = YES; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + isSandboxApp = ![self isProductionApp]; + }); + return isSandboxApp; +} + +- (BOOL)isProductionApp { + const BOOL defaultAppTypeProd = YES; + + NSError *error = nil; + + Class envClass = NSClassFromString(@"FIRAppEnvironmentUtil"); + SEL isSimulatorSelector = NSSelectorFromString(@"isSimulator"); + if ([envClass respondsToSelector:isSimulatorSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([envClass performSelector:isSimulatorSelector]) { +#pragma clang diagnostic pop + [self logAPNSConfigurationError:@"Running InstanceID on a simulator doesn't have APNS. " + @"Use prod profile by default."]; + return defaultAppTypeProd; + } + } + + NSString *path = [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent:@"embedded.mobileprovision"]; + + // Apps distributed via AppStore or TestFlight use the Production APNS certificates. + SEL isFromAppStoreSelector = NSSelectorFromString(@"isFromAppStore"); + if ([envClass respondsToSelector:isFromAppStoreSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([envClass performSelector:isFromAppStoreSelector]) { +#pragma clang diagnostic pop + return defaultAppTypeProd; + } + } + + SEL isAppStoreReceiptSandboxSelector = NSSelectorFromString(@"isAppStoreReceiptSandbox"); + if ([envClass respondsToSelector:isAppStoreReceiptSandboxSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([envClass performSelector:isAppStoreReceiptSandboxSelector] && !path.length) { +#pragma clang diagnostic pop + // Distributed via TestFlight + return defaultAppTypeProd; + } + } + + NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error]; + + if (!profileData.length || error) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the + // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit + // ASCII. Replace any 0s or invalid characters in the input. + uint8_t *profileBytes = (uint8_t *)profileData.bytes; + for (int i = 0; i < profileData.length; i++) { + uint8_t currentByte = profileBytes[i]; + if (!currentByte || currentByte > 127) { + profileBytes[i] = '.'; + } + } + + NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes + length:profileData.length + encoding:NSASCIIStringEncoding + freeWhenDone:NO]; + + if (error || !embeddedProfile.length) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; + NSString *plistContents; + if ([scanner scanUpToString:@"" intoString:&plistContents]) { + plistContents = [plistContents stringByAppendingString:@"
"]; + } + } + + if (!plistContents.length) { + return defaultAppTypeProd; + } + + NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; + if (!data.length) { + [self logAPNSConfigurationError:@"Couldn't read plist fetched from embedded mobileprovision"]; + return defaultAppTypeProd; + } + + NSError *plistMapError; + id plistData = [NSPropertyListSerialization propertyListWithData:data + options:NSPropertyListImmutable + format:nil + error:&plistMapError]; + if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { + NSString *errorString = + [NSString stringWithFormat:@"Error while converting assumed plist to dict %@", + plistMapError.localizedDescription]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + NSDictionary *plistMap = (NSDictionary *)plistData; + + if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID012, + @"Provisioning profile has specifically provisioned devices, " + @"most likely a Dev profile."); + } + + NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey]; + NSString *debugString __unused = + [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID013, @"%@", debugString); + + // No aps-environment in the profile. + if (!apsEnvironment.length) { + [self logAPNSConfigurationError:@"No aps-environment set. If testing on a device APNS is not " + @"correctly configured. Please recheck your provisioning " + @"profiles. If testing on a simulator this is fine since APNS " + @"doesn't work on the simulator."]; + return defaultAppTypeProd; + } + + if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) { + return NO; + } + + return defaultAppTypeProd; +} + +/// Log error messages only when Messaging exists in the pod. +- (void)logAPNSConfigurationError:(NSString *)errorString { + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID014, @"%@", errorString); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID015, @"%@", errorString); + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h new file mode 100644 index 0000000..92b2469 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an APNS device token and whether its environment is for sandbox. + * It can read from and write to an NSDictionary for simple serialization. + */ +@interface FIRInstanceIDAPNSInfo : NSObject + +/// The APNs device token, provided by the OS to the application delegate +@property(nonatomic, readonly, strong) NSData *deviceToken; +/// Represents whether or not this is deviceToken is for the sandbox +/// environment, or production. +@property(nonatomic, readonly, getter=isSandbox) BOOL sandbox; + +/** + * Initializes the receiver with an APNs device token, and boolean + * representing whether that token is for the sandbox environment. + * + * @param deviceToken The APNs device token typically provided by the + * operating system. + * @param isSandbox YES if the APNs device token is for the sandbox + * environment, or NO if it is for production. + * @return An instance of FIRInstanceIDAPNSInfo. + */ +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox; + +/** + * Initializes the receiver from a token options dictionary containing data + * within the `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey` keys. The token should be an + * NSData blob, and the sandbox value should be an NSNumber + * representing a boolean value. + * + * @param dictionary A dictionary containing values under the keys + * `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey`. + * @return An instance of FIRInstanceIDAPNSInfo, or nil if the + * dictionary data was invalid or missing. + */ +- (nullable instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary; + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m new file mode 100644 index 0000000..d1f9d08 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAPNSInfo.h" + +#import "FIRInstanceIDConstants.h" + +/// The key used to find the APNs device token in an archive. +NSString *const kFIRInstanceIDAPNSInfoTokenKey = @"device_token"; +/// The key used to find the sandbox value in an archive. +NSString *const kFIRInstanceIDAPNSInfoSandboxKey = @"sandbox"; + +@implementation FIRInstanceIDAPNSInfo + +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox { + self = [super init]; + if (self) { + _deviceToken = [deviceToken copy]; + _sandbox = isSandbox; + } + return self; +} + +- (instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary { + id deviceToken = dictionary[kFIRInstanceIDTokenOptionsAPNSKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + + id isSandbox = dictionary[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if (![isSandbox isKindOfClass:[NSNumber class]]) { + return nil; + } + self = [super init]; + if (self) { + _deviceToken = (NSData *)deviceToken; + _sandbox = ((NSNumber *)isSandbox).boolValue; + } + return self; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey]; + return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.deviceToken forKey:kFIRInstanceIDAPNSInfoTokenKey]; + [aCoder encodeBool:self.sandbox forKey:kFIRInstanceIDAPNSInfoSandboxKey]; +} + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo { + if ([super isEqual:otherInfo]) { + return YES; + } + return ([self.deviceToken isEqualToData:otherInfo.deviceToken] && + self.isSandbox == otherInfo.isSandbox); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h new file mode 100644 index 0000000..347ddda --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h @@ -0,0 +1,98 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *__nonnull const kFIRInstanceIDKeychainWildcardIdentifier; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper around storing FCM auth data in iOS keychain. + */ +@interface FIRInstanceIDAuthKeychain : NSObject + +/** + * Designated Initializer. Init a generic `SecClassGenericPassword` keychain with `identifier` + * as the `kSecAttrGeneric`. + * + * @param identifier The generic attribute to be used by the keychain. + * + * @return A Keychain object with `kSecAttrGeneric` attribute set to identifier. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier; + +/** + * Get keychain items matching the given service and account. The service and/or account + * can be a wildcard (`kFIRInstanceIDKeychainWildcardIdentifier`), which case the query + * will include all items matching any services and/or accounts. + * + * @param service The kSecAttrService used to save the password. Can be wildcard. + * @param account The kSecAttrAccount used to save the password. Can be wildcard. + * + * @return An array of |NSData|s matching the provided inputs. + */ +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account; + +/** + * Get keychain item for a given service and account. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * + * @return A cached keychain item for a given account and service, or nil if it was not + * found or could not be retrieved. + */ +- (NSData *)dataForService:(NSString *)service account:(NSString *)account; + +/** + * Remove the cached items from the keychain matching the service, account and access group. + * In case the items do not exist, YES is returned but with a valid error object with code + * `errSecItemNotFound`. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * @param handler The callback handler which is invoked when the remove operation is complete, with + * an error if there is any. + */ +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *error))handler; + +/** + * Set the data for a given service and account with a specific accessibility. If + * accessibility is NULL we use `kSecAttrAccessibleAlwaysThisDeviceOnly` which + * prevents backup and restore to iCloud, and works for app extension that can + * execute right after a device is restarted (and not unlocked). + * + * @param data The data to save. + * @param service The `kSecAttrService` used to save the password. + * @param accessibility The `kSecAttrAccessibility` used to save the password. If NULL + * set this to `kSecAttrAccessibleAlwaysThisDeviceOnly`. + * @param account The `kSecAttrAccount` used to save the password. + * @param handler The callback handler which is invoked when the add operation is complete, + * with an error if there is any. + * + */ +- (void)setData:(NSData *)data + forService:(NSString *)service + accessibility:(nullable CFTypeRef)accessibility + account:(NSString *)account + handler:(nullable void (^)(NSError *))handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m new file mode 100644 index 0000000..f75362f --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m @@ -0,0 +1,215 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" + +/** + * The error type representing why we couldn't read data from the keychain. + */ +typedef NS_ENUM(int, FIRInstanceIDKeychainErrorType) { + kFIRInstanceIDKeychainErrorBadArguments = -1301, +}; + +NSString *const kFIRInstanceIDKeychainWildcardIdentifier = @"*"; + +@interface FIRInstanceIDAuthKeychain () + +@property(nonatomic, copy) NSString *generic; +// cachedKeychainData is keyed by service and account, the value is an array of NSData. +// It is used to cache the tokens per service, per account, as well as checkin data per service, +// per account inside the keychain. +@property(nonatomic) + NSMutableDictionary *> *> + *cachedKeychainData; + +@end + +@implementation FIRInstanceIDAuthKeychain + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + _generic = [identifier copy]; + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } + return self; +} + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service + account:(NSString *)account + generic:(NSString *)generic { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + if ([generic length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:generic]) { + finalQuery[(__bridge NSString *)kSecAttrGeneric] = generic; + } + if ([account length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:account]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + if ([service length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:service]) { + finalQuery[(__bridge NSString *)kSecAttrService] = service; + } + return finalQuery; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account generic:self.generic]; +} + +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account { + // If query wildcard service, it asks for all the results, which always query from keychain. + if (![service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + ![account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + _cachedKeychainData[service][account]) { + // As long as service, account array exist, even it's empty, it means we've queried it before, + // returns the cache value. + return _cachedKeychainData[service][account]; + } + + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + + NSMutableArray *results; + keychainQuery[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + // FIRInstanceIDKeychain should only take a query and return a result, will handle the query here. + NSArray *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); + + if (!passwordInfos) { + // Nothing was found, simply return from this sync block. + // Make sure to label the cache entry empty, signaling that we've queried this entry. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return @[]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + return @[]; + } + NSInteger numPasswords = passwordInfos.count; + results = [[NSMutableArray alloc] init]; + for (NSUInteger i = 0; i < numPasswords; i++) { + NSDictionary *passwordInfo = [passwordInfos objectAtIndex:i]; + if (passwordInfo[(__bridge id)kSecValueData]) { + [results addObject:passwordInfo[(__bridge id)kSecValueData]]; + } + } + + // We query the keychain because it didn't exist in cache, now query is done, update the result in + // the cache. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return [results copy]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:[results copy] forKey:account]; + } else { + NSMutableDictionary *entry = [@{account : [results copy]} mutableCopy]; + [_cachedKeychainData setObject:entry forKey:service]; + } + return [results copy]; +} + +- (NSData *)dataForService:(NSString *)service account:(NSString *)account { + NSArray *items = [self itemsMatchingService:service account:account]; + // If items is nil or empty, nil will be returned. + return items.firstObject; +} + +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *error))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all keychain items. + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } else if ([account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all entries under service, + if (_cachedKeychainData[service]) { + _cachedKeychainData[service] = [[NSMutableDictionary alloc] init]; + } + } else if (_cachedKeychainData[service]) { + // We should keep the service/account entry instead of nil so we know + // it's "empty entry" instead of "not query from keychain yet". + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:keychainQuery handler:handler]; +} + +- (void)setData:(NSData *)data + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + handler:(void (^)(NSError *))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + if (handler) { + handler([NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:kFIRInstanceIDKeychainErrorBadArguments + userInfo:nil]); + } + return; + } + [self removeItemsMatchingService:service + account:account + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (data.length > 0) { + NSMutableDictionary *keychainQuery = + [self keychainQueryForService:service account:account]; + keychainQuery[(__bridge id)kSecValueData] = data; + + if (accessibility != NULL) { + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)accessibility; + } else { + // Defaults to No backup + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly; + } + [[FIRInstanceIDKeychain sharedInstance] + addItemWithQuery:keychainQuery + handler:handler]; + } + }]; + // Set the cache value. This must happen after removeItemsMatchingService:account:handler was + // called, so the cache value was reset before setting a new value. + if (_cachedKeychainData[service]) { + if (_cachedKeychainData[service][account]) { + _cachedKeychainData[service][account] = @[ data ]; + } else { + [_cachedKeychainData[service] setObject:@[ data ] forKey:account]; + } + } else { + [_cachedKeychainData setObject:[@{account : @[ data ]} mutableCopy] forKey:service]; + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h new file mode 100644 index 0000000..1fb715e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "FIRInstanceIDCheckinService.h" + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDStore; + +/** + * FIRInstanceIDAuthService is responsible for retrieving, caching, and supplying checkin info + * for the rest of Instance ID. A checkin can be scheduled, meaning that it will keep retrying the + * checkin request until it is successful. A checkin can also be requested directly, with a + * completion handler. + */ +@interface FIRInstanceIDAuthService : NSObject + +/** + * Used only for testing. In addition to taking a store (for locally caching the checkin info), it + * also takes a checkinService. + */ +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store; + +/** + * Initializes the auth service given a store (which provides the local caching of checkin info). + * This initializer will create its own instance of FIRInstanceIDCheckinService. + */ +- (instancetype)initWithStore:(FIRInstanceIDStore *)store; + +#pragma mark - Checkin Service + +/** + * Checks if the current deviceID and secret are valid or not. + * + * @return YES if the checkin credentials are valid else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Fetch checkin info from the server. This would usually refresh the existing + * checkin credentials for the current app. + * + * @param handler The completion handler to invoke once the checkin info has been + * refreshed. + */ +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Schedule checkin. Will hit the network only if the currently loaded checkin + * preferences are stale. + * + * @param immediately YES if we want it to be scheduled immediately else NO. + */ +- (void)scheduleCheckin:(BOOL)immediately; + +/** + * Returns the checkin preferences currently loaded in memory. The Checkin preferences + * can be either valid or invalid. + * + * @return The checkin preferences loaded in memory. + */ +- (FIRInstanceIDCheckinPreferences *)checkinPreferences; + +/** + * Cancels any ongoing checkin fetch, if any. + */ +- (void)stopCheckinRequest; + +/** + * Resets the checkin information. + * + * @param handler The callback handler which is invoked when checkin reset is complete, + * with an error if there is any. + */ +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m new file mode 100644 index 0000000..8c33c44 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m @@ -0,0 +1,302 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "NSError+FIRInstanceID.h" + +// Max time interval between checkin retry in seconds. +static const int64_t kMaxCheckinRetryIntervalInSeconds = 1 << 5; + +@interface FIRInstanceIDAuthService () + +// Used to retrieve and cache the checkin info to disk and Keychain. +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *store; +// Used to perform single checkin fetches. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinService *checkinService; +// The current checkin info. It will be compared to what is retrieved to determine whether it is +// different than what is in the cache. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; + +// This array will track multiple handlers waiting for checkin to be performed. When a checkin +// request completes, all the handlers will be notified. +// Changes to the checkinHandlers array should happen in a thread-safe manner. +@property(nonatomic, readonly, strong) + NSMutableArray *checkinHandlers; + +// This is set to true if there is a checkin request in-flight. +@property(atomic, readwrite, assign) BOOL isCheckinInProgress; +// This timer is used a perform checkin retries. It is cancellable. +@property(atomic, readwrite, strong) NSTimer *scheduledCheckinTimer; +// The number of times checkin has been retried during a scheduled checkin. +@property(atomic, readwrite, assign) int checkinRetryCount; + +@end + +@implementation FIRInstanceIDAuthService + +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store { + self = [super init]; + if (self) { + _store = store; + _checkinPreferences = [_store cachedCheckinPreferences]; + _checkinService = checkinService; + _checkinHandlers = [NSMutableArray array]; + } + return self; +} + +- (void)dealloc { + [_scheduledCheckinTimer invalidate]; +} + +- (instancetype)initWithStore:(FIRInstanceIDStore *)store { + FIRInstanceIDCheckinService *checkinService = [[FIRInstanceIDCheckinService alloc] init]; + return [self initWithCheckinService:checkinService store:store]; +} + +#pragma mark - Schedule Checkin + +- (void)scheduleCheckin:(BOOL)immediately { + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + // Checkin is already scheduled, so this (non-immediate) request can be ignored. + if (!immediately && [self.scheduledCheckinTimer isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService000, + @"Checkin sync already scheduled. Will not schedule."); + return; + } + + if (immediately) { + [self performScheduledCheckin]; + } else { + int64_t checkinRetryDuration = [self calculateNextCheckinRetryIntervalInSeconds]; + [self startCheckinTimerWithDuration:(NSTimeInterval)checkinRetryDuration]; + } +} + +- (void)startCheckinTimerWithDuration:(NSTimeInterval)timerDuration { + self.scheduledCheckinTimer = + [NSTimer scheduledTimerWithTimeInterval:timerDuration + target:self + selector:@selector(onScheduledCheckinTimerFired:) + userInfo:nil + repeats:NO]; + // Add some tolerance to the timer, to allow iOS to be more flexible with this timer + self.scheduledCheckinTimer.tolerance = 0.5; +} + +- (void)clearScheduledCheckinTimer { + [self.scheduledCheckinTimer invalidate]; + self.scheduledCheckinTimer = nil; +} + +- (void)onScheduledCheckinTimerFired:(NSTimer *)timer { + [self performScheduledCheckin]; +} + +- (void)performScheduledCheckin { + // No checkin scheduled as of now. + [self clearScheduledCheckinTimer]; + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + FIRInstanceID_WEAKIFY(self); + [self + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + self.checkinRetryCount++; + + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService001, @"Checkin error %@.", + error); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Schedule another checkin + [self scheduleCheckin:NO]; + }); + + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService002, @"Checkin success."); + } + }]; +} + +- (int64_t)calculateNextCheckinRetryIntervalInSeconds { + // persistent failures can lead to overflow prevent that. + if (self.checkinRetryCount >= 10) { + return kMaxCheckinRetryIntervalInSeconds; + } + return MIN(1 << self.checkinRetryCount, kMaxCheckinRetryIntervalInSeconds); +} + +#pragma mark - Checkin Service + +- (BOOL)hasValidCheckinInfo { + return [self.checkinPreferences hasValidCheckinInfo]; +} + +- (void)fetchCheckinInfoWithHandler:(nonnull FIRInstanceIDDeviceCheckinCompletion)handler { + // Perform any changes to self.checkinHandlers and _isCheckinInProgress in a thread-safe way. + @synchronized(self) { + [self.checkinHandlers addObject:handler]; + + if (_isCheckinInProgress) { + // Nothing more to do until our checkin request is done + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress, + @"Checkin is in progress\n"); + return; + } + } + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + [self notifyCheckinHandlersWithCheckin:self.checkinPreferences error:nil]; + return; + } + + @synchronized(self) { + _isCheckinInProgress = YES; + } + [self.checkinService + checkinWithExistingCheckin:self.checkinPreferences + completion:^(FIRInstanceIDCheckinPreferences *checkinPreferences, + NSError *error) { + @synchronized(self) { + self->_isCheckinInProgress = NO; + } + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService003, + @"Failed to checkin device %@", error); + [self notifyCheckinHandlersWithCheckin:nil error:error]; + return; + } + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService004, + @"Successfully got checkin credentials"); + BOOL hasSameCachedPreferences = + [self cachedCheckinMatchesCheckin:checkinPreferences]; + checkinPreferences.hasPreCachedAuthCredentials = hasSameCachedPreferences; + + // Update to the most recent checkin preferences + self.checkinPreferences = checkinPreferences; + + // Save the checkin info to disk + // Keychain might not be accessible, so confirm that checkin preferences can + // be saved + [self.store + saveCheckinPreferences:checkinPreferences + handler:^(NSError *checkinSaveError) { + if (checkinSaveError && !hasSameCachedPreferences) { + // The checkin info was new, but it couldn't be + // written to the Keychain. Delete any stuff that was + // cached in memory. This doesn't delete any + // previously persisted preferences. + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeService004, + @"Unable to save checkin info, resetting " + @"checkin preferences " + "in memory."); + [checkinPreferences reset]; + [self + notifyCheckinHandlersWithCheckin:nil + error: + checkinSaveError]; + } else { + // The checkin is either new, or it was the same (and + // it couldn't be saved). Either way, report that the + // checkin preferences were received successfully. + [self notifyCheckinHandlersWithCheckin: + checkinPreferences + error:nil]; + if (!hasSameCachedPreferences) { + // Checkin is new. + // Notify any listeners that might be waiting for + // checkin to be fetched, such as Firebase + // Messaging (for its MCS connection). + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] + postNotificationName: + kFIRInstanceIDCheckinFetchedNotification + object:nil]; + }); + } + } + }]; + }]; +} + +- (FIRInstanceIDCheckinPreferences *)checkinPreferences { + return _checkinPreferences; +} + +- (void)stopCheckinRequest { + [self.checkinService stopFetching]; +} + +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler { + [self.store removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + self.checkinPreferences = nil; + } + if (handler) { + handler(error); + } + }]; +} + +#pragma mark - Private + +/** + * Goes through the current list of checkin handlers and fires them with the same checkin and/or + * error info. The checkin handlers will get cleared after. + */ +- (void)notifyCheckinHandlersWithCheckin:(nullable FIRInstanceIDCheckinPreferences *)checkin + error:(nullable NSError *)error { + @synchronized(self) { + for (FIRInstanceIDDeviceCheckinCompletion handler in self.checkinHandlers) { + handler(checkin, error); + } + [self.checkinHandlers removeAllObjects]; + } +} + +/** + * Given a |checkin|, it will compare it to the current checkinPreferences to see if the + * deviceID and secretToken are the same. + */ +- (BOOL)cachedCheckinMatchesCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + if (self.checkinPreferences && checkin) { + return ([self.checkinPreferences.deviceID isEqualToString:checkin.deviceID] && + [self.checkinPreferences.secretToken isEqualToString:checkin.secretToken]); + } + return NO; +} +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h new file mode 100644 index 0000000..bccaced --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDBackupExcludedPlist : NSObject + +/** + * Caches the plist contents in memory so we don't hit the disk each time we want + * to query something in the plist. This is loaded lazily i.e. if you write to the + * plist the contents you want to write will be stored here if the write was + * successful. The other case where it is loaded is if you read the plist contents + * by calling `contentAsDictionary`. + * + * In case you write to the plist and then try to read the file using + * `contentAsDictionary` we would just return the cachedPlistContents since it would + * represent the disk contents. + */ +@property(nonatomic, readonly, strong) NSDictionary *cachedPlistContents; + +/** + * Init a backup excluded plist file. + * + * @param fileName The filename for the plist file. + * @param subDirectory The subdirectory in Application Support to save the plist. + * + * @return Helper which allows to read write data to a backup excluded plist. + */ +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory; + +/** + * Write dictionary data to the backup excluded plist file. If the file does not exist + * it would be created before writing to it. + * + * @param dict The data to be written to the plist. + * @param error The error object if any while writing the data. + * + * @return YES if the write was successful else NO. + */ +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error; + +/** + * Delete the backup excluded plist created with the above filename. + * + * @param error The error object if any while deleting the file. + * + * @return YES If the delete was successful else NO. + */ +- (BOOL)deleteFile:(NSError **)error; + +/** + * The contents of the plist file. We also store the contents of the file in-memory. + * If the in-memory contents are valid we return the in-memory contents else we read + * the file from disk. + * + * @return A dictionary object that contains the contents of the plist file if the file + * exists else nil. + */ +- (NSDictionary *)contentAsDictionary; + +/** + * Check if the plist exists on the disk or not. + * + * @return YES if the file exists on the disk else NO. + */ +- (BOOL)doesFileExist; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m new file mode 100644 index 0000000..2c32222 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m @@ -0,0 +1,206 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDBackupExcludedPlist.h" + +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" + +typedef enum : NSUInteger { + FIRInstanceIDPlistDirectoryUnknown, + FIRInstanceIDPlistDirectoryDocuments, + FIRInstanceIDPlistDirectoryApplicationSupport, +} FIRInstanceIDPlistDirectory; + +@interface FIRInstanceIDBackupExcludedPlist () + +@property(nonatomic, readwrite, copy) NSString *fileName; +@property(nonatomic, readwrite, copy) NSString *subDirectoryName; +@property(nonatomic, readwrite, assign) BOOL fileInStandardDirectory; + +@property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents; + +@end + +@implementation FIRInstanceIDBackupExcludedPlist + +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory { + self = [super init]; + if (self) { + _fileName = [fileName copy]; + _subDirectoryName = [subDirectory copy]; +#if TARGET_OS_IOS + _fileInStandardDirectory = [self moveToApplicationSupportSubDirectory:subDirectory]; +#else + // For tvOS and macOS, we never store the content in document folder, so + // the migration is unnecessary. + _fileInStandardDirectory = YES; +#endif + } + return self; +} + +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error { + NSString *path = [self plistPathInDirectory:[self plistDirectory]]; + if (![dict writeToFile:path atomically:YES]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000, + @"Failed to write to %@.plist", self.fileName); + return NO; + } + + // Successfully wrote contents -- change the in-memory contents + self.cachedPlistContents = [dict copy]; + + _FIRInstanceIDDevAssert([[NSFileManager defaultManager] fileExistsAtPath:path], + @"Error writing data to non-backed up plist %@.plist", self.fileName); + + NSURL *URL = [NSURL fileURLWithPath:path]; + if (error) { + *error = nil; + } + + NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ] + error:error]; + if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) { + return YES; + } + + BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error]; + if (!success) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001, + @"Error excluding %@ from backup, %@", [URL lastPathComponent], + error ? *error : @""); + } + return success; +} + +- (BOOL)deleteFile:(NSError **)error { + BOOL success = YES; + NSString *path = [self plistPathInDirectory:[self plistDirectory]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + success = [[NSFileManager defaultManager] removeItemAtPath:path error:error]; + } + // remove the in-memory contents + self.cachedPlistContents = nil; + return success; +} + +- (NSDictionary *)contentAsDictionary { + if (!self.cachedPlistContents) { + NSString *path = [self plistPathInDirectory:[self plistDirectory]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path]; + } + } + return self.cachedPlistContents; +} + +- (BOOL)moveToApplicationSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + // This only going to happen inside iOS so it is an applicationSupportDirectory. + NSString *applicationSupportDirPath = directoryPaths.lastObject; + NSArray *components = @[ applicationSupportDirPath, subDirectoryName ]; + NSString *subDirectoryPath = [NSString pathWithComponents:components]; + BOOL hasSubDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + // Cannot move to non-existent directory + return NO; + } + + if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryDocuments]) { + NSString *oldPlistPath = [self plistPathInDirectory:FIRInstanceIDPlistDirectoryDocuments]; + NSString *newPlistPath = + [self plistPathInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport]; + if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport]) { + // File exists in both Documents and ApplicationSupport + return NO; + } + NSError *moveError; + if (![[NSFileManager defaultManager] moveItemAtPath:oldPlistPath + toPath:newPlistPath + error:&moveError]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist002, + @"Failed to move file %@ from %@ to %@. Error: %@", self.fileName, + oldPlistPath, newPlistPath, moveError); + return NO; + } + } + // We moved the file if it existed, otherwise we didn't need to do anything + return YES; +} + +- (BOOL)doesFileExist { + return [self doesFileExistInDirectory:[self plistDirectory]]; +} + +#pragma mark - Private + +- (FIRInstanceIDPlistDirectory)plistDirectory { + if (_fileInStandardDirectory) { + return FIRInstanceIDPlistDirectoryApplicationSupport; + } else { + return FIRInstanceIDPlistDirectoryDocuments; + }; +} + +- (NSString *)plistPathInDirectory:(FIRInstanceIDPlistDirectory)directory { + return [self pathWithName:self.fileName inDirectory:directory]; +} + +- (NSString *)pathWithName:(NSString *)plistName + inDirectory:(FIRInstanceIDPlistDirectory)directory { + NSArray *directoryPaths; + NSArray *components = @[]; + NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", plistName]; + switch (directory) { + case FIRInstanceIDPlistDirectoryDocuments: + directoryPaths = + NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + components = @[ directoryPaths.lastObject, plistNameWithExtension ]; + break; + + case FIRInstanceIDPlistDirectoryApplicationSupport: + directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + break; + + default: + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum, + @"Invalid plist directory type: %lu", (unsigned long)directory); + NSAssert(NO, @"Invalid plist directory type: %lu", (unsigned long)directory); + break; + } + + return [NSString pathWithComponents:components]; +} + +- (BOOL)doesFileExistInDirectory:(FIRInstanceIDPlistDirectory)directory { + NSString *path = [self plistPathInDirectory:directory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h new file mode 100644 index 0000000..a62fad1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +@interface FIRInstanceIDCheckinPreferences (Internal) + +/** + * Parse the checkin auth credentials saved in the Keychain to initialize checkin + * preferences. + * + * @param keychainContent The checkin auth credentials saved in the Keychain. + * + * @return A valid checkin preferences object if the checkin auth credentials in the + * keychain can be parsed successfully else nil. + */ ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent; + +/** + * Default initializer for InstanceID checkin preferences. + * + * @param deviceID The deviceID for the app. + * @param secretToken The secret token the app uses to authenticate with the server. + * + * @return A checkin preferences object with given deviceID and secretToken. + */ +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken; + +/** + * Update checkin preferences from the preferences dict persisted as a plist. The dict contains + * all the checkin preferences retrieved from the server except the deviceID and secret which + * are stored in the Keychain. + * + * @param checkinPlistContent The checkin preferences saved in a plist on the disk. + */ +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent; + +/** + * Reset the current checkin preferences object. + */ +- (void)reset; + +/** + * The string that contains the checkin auth credentials i.e. deviceID and secret. This + * needs to be stored in the Keychain. + * + * @return The checkin auth credential string containing the deviceID and secret. + */ +- (NSString *)checkinKeychainContent; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m new file mode 100644 index 0000000..88cc40a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences+Internal.h" + +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kCheckinKeychainContentSeparatorString = @"|"; + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +@end + +@implementation FIRInstanceIDCheckinPreferences (Internal) + ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent { + NSString *deviceID = [self checkinDeviceIDFromKeychainContent:keychainContent]; + NSString *secret = [self checkinSecretFromKeychainContent:keychainContent]; + if ([deviceID length] && [secret length]) { + return [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceID secretToken:secret]; + } else { + return nil; + } +} + +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken { + self = [super init]; + if (self) { + self.deviceID = [deviceID copy]; + self.secretToken = [secretToken copy]; + } + return self; +} + +- (void)reset { + self.deviceID = nil; + self.secretToken = nil; + self.digest = nil; + self.versionInfo = nil; + self.gServicesData = nil; + self.deviceDataVersion = nil; + self.lastCheckinTimestampMillis = 0; +} + +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent { + for (NSString *key in checkinPlistContent) { + if ([kFIRInstanceIDDigestStringKey isEqualToString:key]) { + self.digest = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDVersionInfoStringKey isEqualToString:key]) { + self.versionInfo = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDLastCheckinTimeKey isEqualToString:key]) { + self.lastCheckinTimestampMillis = [checkinPlistContent[key] longLongValue]; + } else if ([kFIRInstanceIDGServicesDictionaryKey isEqualToString:key]) { + self.gServicesData = [checkinPlistContent[key] mutableCopy]; + } else if ([kFIRInstanceIDDeviceDataVersionKey isEqualToString:key]) { + self.deviceDataVersion = [checkinPlistContent[key] copy]; + } + // Otherwise we have some keys we don't care about + } +} + +- (NSString *)checkinKeychainContent { + if ([self.deviceID length] && [self.secretToken length]) { + return [NSString stringWithFormat:@"%@%@%@", self.deviceID, + kCheckinKeychainContentSeparatorString, self.secretToken]; + } else { + return nil; + } +} + ++ (NSString *)checkinDeviceIDFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:0]; +} + ++ (NSString *)checkinSecretFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:1]; +} + ++ (NSString *)checkinKeychainContent:(NSString *)keychainContent forIndex:(int)index { + NSArray *keychainComponents = + [keychainContent componentsSeparatedByString:kCheckinKeychainContentSeparatorString]; + if (index >= 0 && index < 2 && [keychainComponents count] == 2) { + return keychainComponents[index]; + } else { + return nil; + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h new file mode 100644 index 0000000..fe459af --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The preferences InstanceID loads from checkin server. The deviceID and secret that checkin + * provides is used to authenticate all future requests to the server. Besides the deviceID + * and secret the other information that checkin provides is stored in a plist on the device. + * The deviceID and secret are persisted in the device keychain. + */ +@interface FIRInstanceIDCheckinPreferences : NSObject + +/** + * DeviceID and secretToken are the checkin auth credentials and are stored in the Keychain. + */ +@property(nonatomic, readonly, copy) NSString *deviceID; +@property(nonatomic, readonly, copy) NSString *secretToken; + +/** + * All the other checkin preferences other than deviceID and secret are stored in a plist. + */ +@property(nonatomic, readonly, copy) NSString *deviceDataVersion; +@property(nonatomic, readonly, copy) NSString *digest; +@property(nonatomic, readonly, copy) NSString *versionInfo; +@property(nonatomic, readonly, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readonly, assign) int64_t lastCheckinTimestampMillis; + +/** + * The content retrieved from checkin server that should be persisted in a plist. This + * doesn't contain the deviceID and secret which are stored in the Keychain since they + * should be more private. + * + * @return The checkin preferences that should be persisted in a plist. + */ +- (NSDictionary *)checkinPlistContents; + +/** + * Return whether checkin info exists, valid or not. + */ +- (BOOL)hasCheckinInfo; + +/** + * Verify if checkin preferences are valid or not. + * + * @return YES if valid checkin preferences else NO. + */ +- (BOOL)hasValidCheckinInfo; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m new file mode 100644 index 0000000..2479a85 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m @@ -0,0 +1,97 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +#import +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDUtilities.h" + +const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval = 7 * 24 * 60 * 60; // 7 days. + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +// This flag indicates that we have already saved the above deviceID and secret +// to our keychain and hence we don't need to save again. This is helpful since +// on checkin refresh we can avoid writing to the Keychain which can sometimes +// be very buggy. For info check this https://forums.developer.apple.com/thread/4743 +@property(nonatomic, readwrite, assign) BOOL hasPreCachedAuthCredentials; + +@end + +@implementation FIRInstanceIDCheckinPreferences + +- (NSDictionary *)checkinPlistContents { + NSMutableDictionary *checkinPlistContents = [NSMutableDictionary dictionary]; + checkinPlistContents[kFIRInstanceIDDigestStringKey] = self.digest ?: @""; + checkinPlistContents[kFIRInstanceIDVersionInfoStringKey] = self.versionInfo ?: @""; + checkinPlistContents[kFIRInstanceIDDeviceDataVersionKey] = self.deviceDataVersion ?: @""; + checkinPlistContents[kFIRInstanceIDLastCheckinTimeKey] = @(self.lastCheckinTimestampMillis); + checkinPlistContents[kFIRInstanceIDGServicesDictionaryKey] = + [self.gServicesData count] ? self.gServicesData : @{}; + return checkinPlistContents; +} + +- (BOOL)hasCheckinInfo { + return (self.deviceID.length && self.secretToken.length); +} + +- (BOOL)hasValidCheckinInfo { + int64_t currentTimestampInMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + int64_t timeSinceLastCheckinInMillis = currentTimestampInMillis - self.lastCheckinTimestampMillis; + _FIRInstanceIDDevAssert(timeSinceLastCheckinInMillis >= 0, + @"FCM error: cannot have last checkin timestamp in future"); + BOOL hasCheckinInfo = [self hasCheckinInfo]; + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + // If it's app's first time open and checkin is already fetched and no locale information is + // stored, then checkin info is valid. We should not checkin again because locale is considered + // "changed". + if (hasCheckinInfo && !lastLocale) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return YES; + } + + // If locale has changed, checkin info is no longer valid. + // Also update locale information if changed. (Only do it here not in token refresh) + if (FIRInstanceIDHasLocaleChanged()) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return NO; + } + + return (hasCheckinInfo && + (timeSinceLastCheckinInMillis / 1000.0 < kFIRInstanceIDDefaultCheckinInterval)); +} + +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials { + _hasPreCachedAuthCredentials = hasPreCachedAuthCredentials; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h new file mode 100644 index 0000000..23b55e1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +/** Checkin refresh interval. **/ +FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval; + +@interface FIRInstanceIDCheckinPreferences () + +- (BOOL)hasPreCachedAuthCredentials; +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h new file mode 100644 index 0000000..cc97e47 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstanceIDUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +// keys in Checkin preferences +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceAuthIdKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSecretTokenKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDigestStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDLastCheckinTimeKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDVersionInfoStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDGServicesDictionaryKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceDataVersionKey; + +@class FIRInstanceIDCheckinPreferences; + +/** + * @related FIRInstanceIDCheckinService + * + * The completion handler invoked once the fetch from Checkin server finishes. + * For successful fetches we returned checkin information by the checkin service + * and `nil` error, else we return the appropriate error object as reported by the + * Checkin Service. + * + * @param checkinPreferences The checkin preferences as fetched from the server. + * @param error The error object which fetching GServices data. + */ +typedef void (^FIRInstanceIDDeviceCheckinCompletion)( + FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error); + +/** + * Register the device with Checkin Service and get back the `authID`, `secret + * token` etc. for the client. Checkin results are cached in the + * `FIRInstanceIDCache` and periodically refreshed to prevent them from being stale. + * Each client needs to register with checkin before registering with InstanceID. + */ +@interface FIRInstanceIDCheckinService : NSObject + +/** + * Execute a device checkin request to obtain an deviceID, secret token, + * gService data. + * + * @param existingCheckin An existing checkin preference object, if available. + * @param completion Completion hander called on success or failure of device checkin. + */ +- (void)checkinWithExistingCheckin:(nullable FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion; + +/** + * This would stop any request that the service made to the checkin backend and also + * release any callback handlers that it holds. + */ +- (void)stopFetching; + +/** + * Set test block for mock testing network requests. + * + * @param block The block to invoke as a mock response from the network. + */ ++ (void)setCheckinTestBlock:(nullable FIRInstanceIDURLRequestTestBlock)block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m new file mode 100644 index 0000000..be5b01a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m @@ -0,0 +1,235 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin"; + +// keys in Checkin preferences +NSString *const kFIRInstanceIDDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey"; +NSString *const kFIRInstanceIDSecretTokenKey = @"GMSInstanceIDSecretTokenKey"; +NSString *const kFIRInstanceIDDigestStringKey = @"GMSInstanceIDDigestKey"; +NSString *const kFIRInstanceIDLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey"; +NSString *const kFIRInstanceIDVersionInfoStringKey = @"GMSInstanceIDVersionInfo"; +NSString *const kFIRInstanceIDGServicesDictionaryKey = @"GMSInstanceIDGServicesData"; +NSString *const kFIRInstanceIDDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion"; + +static NSUInteger const kCheckinType = 2; // DeviceType IOS in l/w/a/_checkin.proto +static NSUInteger const kCheckinVersion = 2; +static NSUInteger const kFragment = 0; + +static FIRInstanceIDURLRequestTestBlock testBlock; + +@interface FIRInstanceIDCheckinService () + +@property(nonatomic, readwrite, strong) NSURLSession *session; + +@end + +@implementation FIRInstanceIDCheckinService +; + +- (instancetype)init { + self = [super init]; + if (self) { + // Create an URLSession once, even though checkin should happen about once a day + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + config.allowsCellularAccess = YES; + _session = [NSURLSession sessionWithConfiguration:config]; + _session.sessionDescription = @"com.google.iid-checkin"; + } + return self; +} + +- (void)dealloc { + testBlock = nil; + [self.session invalidateAndCancel]; +} + +- (void)checkinWithExistingCheckin:(FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion { + _FIRInstanceIDDevAssert(completion != nil, @"completion required"); + + if (self.session == nil) { + FIRInstanceIDLoggerError(kFIRIntsanceIDInvalidNetworkSession, + @"Inconsistent state: NSURLSession has been invalidated"); + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]; + completion(nil, error); + return; + } + + NSURL *url = [NSURL URLWithString:kDeviceCheckinURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; + NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin]; + NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters + options:0 + error:nil]; + request.HTTPMethod = @"POST"; + request.HTTPBody = checkinData; + + void (^handler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService000, + @"Device checkin HTTP fetch error. Error Code: %ld", + (long)error.code); + completion(nil, error); + return; + } + + NSError *serializationError; + NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&serializationError]; + if (serializationError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService001, + @"Error serializing json object. Error Code: %ld", + _FIRInstanceID_L(serializationError.code)); + completion(nil, serializationError); + return; + } + + NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue]; + NSString *secretToken = [dataResponse[@"security_token"] stringValue]; + if ([deviceAuthID length] == 0) { + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidRequest]; + completion(nil, error); + return; + } + + int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue]; + int64_t currentTimestampMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + // Somehow the server clock gets out of sync with the device clock. + // Reset the last checkin timestamp in case this happens. + if (lastCheckinTimestampMillis > currentTimestampMillis) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeService002, @"Invalid last checkin timestamp %@ in future.", + [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]); + lastCheckinTimestampMillis = currentTimestampMillis; + } + + NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @""; + NSString *digest = dataResponse[@"digest"] ?: @""; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService003, + @"Checkin successful with authId: %@, " + @"digest: %@, " + @"lastCheckinTimestamp: %lld", + deviceAuthID, digest, lastCheckinTimestampMillis); + + NSString *versionInfo = dataResponse[@"version_info"] ?: @""; + NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary]; + + // Read gServices data. + NSArray *flatSettings = dataResponse[@"setting"]; + for (NSDictionary *dict in flatSettings) { + if (dict[@"name"] && dict[@"value"]) { + gservicesData[dict[@"name"]] = dict[@"value"]; + } else { + _FIRInstanceIDDevAssert(NO, @"Invalid setting in checkin response: (%@: %@)", + dict[@"name"], dict[@"value"]); + } + } + + FIRInstanceIDCheckinPreferences *checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceAuthID + secretToken:secretToken]; + NSDictionary *preferences = @{ + kFIRInstanceIDDigestStringKey : digest, + kFIRInstanceIDVersionInfoStringKey : versionInfo, + kFIRInstanceIDLastCheckinTimeKey : @(lastCheckinTimestampMillis), + kFIRInstanceIDGServicesDictionaryKey : gservicesData, + kFIRInstanceIDDeviceDataVersionKey : deviceDataVersionInfo, + }; + [checkinPreferences updateWithCheckinPlistContents:preferences]; + completion(checkinPreferences, nil); + }; + // Test block + if (testBlock) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService005, + @"Test block set, will not hit the server"); + testBlock(request, handler); + return; + } + + NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler]; + [task resume]; +} + +- (void)stopFetching { + [self.session invalidateAndCancel]; + // The session cannot be reused after invalidation. Dispose it to prevent accident reusing. + self.session = nil; +} + +#pragma mark - Private + +- (NSDictionary *)checkinParametersWithExistingCheckin: + (nullable FIRInstanceIDCheckinPreferences *)checkinPreferences { + NSString *deviceModel = FIRInstanceIDDeviceModel(); + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion]; + + // Get locale from GCM if GCM exists else use system API. + NSString *locale = FIRInstanceIDCurrentLocale(); + + NSInteger userNumber = 0; // Multi Profile may change this. + NSInteger userSerialNumber = 0; // Multi Profile may change this + + uint32_t loggingID = arc4random(); + NSString *timeZone = [NSTimeZone localTimeZone].name; + int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis; + + NSDictionary *checkinParameters = @{ + @"checkin" : @{ + @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion}, + @"type" : @(kCheckinType), + @"user_number" : @(userNumber), + @"last_checkin_msec" : @(lastCheckingTimestampMillis), + }, + @"fragment" : @(kFragment), + @"logging_id" : @(loggingID), + @"locale" : locale, + @"version" : @(kCheckinVersion), + @"digest" : checkinPreferences.digest ?: @"", + @"timezone" : timeZone, + @"user_serial_number" : @(userSerialNumber), + @"id" : @([checkinPreferences.deviceID longLongValue]), + @"security_token" : @([checkinPreferences.secretToken longLongValue]), + }; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService006, @"Checkin parameters: %@", + checkinParameters); + return checkinParameters; +} + ++ (void)setCheckinTestBlock:(FIRInstanceIDURLRequestTestBlock)block { + testBlock = [block copy]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h new file mode 100644 index 0000000..5e1b119 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h @@ -0,0 +1,108 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; + +// These values exposed for testing +extern NSString *const kFIRInstanceIDCheckinKeychainService; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainService; + +/** + * Checkin preferences backing store. + */ +@interface FIRInstanceIDCheckinStore : NSObject + +/** + * Designated Initializer. Initialize a checkin store with the given backup excluded + * plist filename. + * + * @param checkinFilename The backup excluded plist filename to persist checkin + * preferences. + * + * @param subDirectoryName Sub-directory in standard directory where we write + * InstanceID plist. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName; + +/** + * Initialize a checkin store with the given backup excluded plist and keychain. + * + * @param plist The backup excluded plist to persist checkin preferences. + * @param keychain The keychain used to persist checkin auth preferences. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain; + +/** + * Checks whether the backup excluded checkin preferences are present on the disk or not. + * + * @return YES if the backup excluded checkin plist exists on the disks else NO. + */ +- (BOOL)hasCheckinPlist; + +#pragma mark - Save + +/** + * Save the checkin preferences to backing store. + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler; + +#pragma mark - Delete + +/** + * Remove the cached checkin preferences. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler; + +#pragma mark - Get + +/** + * Get the cached device secret. If we cannot access it for some reason we + * return the appropriate error object. + * + * @return The cached checkin preferences if present else nil. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Migrate the checkin item from old service/account to the new one. + * The new account is dynamic as it uses bundle ID. + * This is to ensure checkin is not shared across apps, but still the same + * if app has used GCM before. + * This call should only happen once. + * + */ +- (void)migrateCheckinItemIfNeeded; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m new file mode 100644 index 0000000..99715a5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m @@ -0,0 +1,238 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kFIRInstanceIDCheckinKeychainGeneric = @"com.google.iid"; + +NSString *const kFIRInstanceIDCheckinKeychainService = @"com.google.iid.checkin"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount = @"com.google.iid.checkin-account"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainService = @"com.google.iid.checkin-service"; + +// Checkin plist used to have the deviceID and secret stored in them and that's why they +// had 6 items in it. Since the deviceID and secret have been moved to the keychain +// there would only be 4 items. +static const NSInteger kOldCheckinPlistCount = 6; + +@interface FIRInstanceIDCheckinStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; +// Checkin will store items under +// Keychain account: , +// Keychain service: |kFIRInstanceIDCheckinKeychainService| +@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount; + +@end + +@implementation FIRInstanceIDCheckinStore + +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName { + FIRInstanceIDBackupExcludedPlist *plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinFilename + subDirectory:subDirectoryName]; + + FIRInstanceIDAuthKeychain *keychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDCheckinKeychainGeneric]; + return [self initWithCheckinPlist:plist keychain:keychain]; +} + +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _plist = plist; + _keychain = keychain; + } + return self; +} + +- (BOOL)hasCheckinPlist { + return [self.plist doesFileExist]; +} + +- (NSString *)bundleIdentifierForKeychainAccount { + static NSString *bundleIdentifier; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundleIdentifier = FIRInstanceIDAppIdentifier(); + }); + return bundleIdentifier; +} + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + NSDictionary *checkinPlistContents = [preferences checkinPlistContents]; + NSString *checkinKeychainContent = [preferences checkinKeychainContent]; + + if (![checkinKeychainContent length]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore000, + @"Failed to get checkin keychain content from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + if (![checkinPlistContents count]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore001, + @"Failed to get checkin plist contents from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + + // Save all other checkin preferences in a plist + NSError *error; + if (![self.plist writeDictionary:checkinPlistContents error:&error]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore003, + @"Failed to save checkin plist contents." + @"Will delete auth credentials"); + [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + if (handler) { + handler(error); + } + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved, + @"Checkin plist file is saved"); + + // Save the deviceID and secret in the Keychain + if (!preferences.hasPreCachedAuthCredentials) { + NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding]; + [self.keychain setData:data + forService:kFIRInstanceIDCheckinKeychainService + accessibility:nil + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + } else { + handler(nil); + } +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler { + // Delete the checkin preferences plist first to avoid delay. + NSError *deletePlistError; + if (![self.plist deleteFile:&deletePlistError]) { + handler(deletePlistError); + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted, + @"Deleted checkin plist file."); + // Remove deviceID and secret from Keychain + [self.keychain + removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + // Try to remove from old location as well because migration + // is no longer needed. Consider this is either a fresh install + // or an identity wipe. + [self.keychain + removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + handler(error); + }]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + // Query the keychain for deviceID and secret + NSData *item = [self.keychain dataForService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount]; + + // Check info found in keychain + NSString *checkinKeychainContent = [[NSString alloc] initWithData:item + encoding:NSUTF8StringEncoding]; + FIRInstanceIDCheckinPreferences *checkinPreferences = + [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:checkinKeychainContent]; + + NSDictionary *checkinPlistContents = [self.plist contentAsDictionary]; + + NSString *plistDeviceAuthID = checkinPlistContents[kFIRInstanceIDDeviceAuthIdKey]; + NSString *plistSecretToken = checkinPlistContents[kFIRInstanceIDSecretTokenKey]; + + // If deviceID and secret not found in the keychain verify that we don't have them in the + // checkin preferences plist. + if (![checkinPreferences.deviceID length] && ![checkinPreferences.secretToken length]) { + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + // Couldn't find checkin credentials in keychain but found them in the plist. + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } else { + // Couldn't find checkin credentials in keychain nor plist + return nil; + } + } else if (kOldCheckinPlistCount == checkinPlistContents.count) { + // same check as above but just to be extra sure that we cover all upgrade cases properly. + // TODO(chliangGoogle): Remove this case, after verifying it's not needed + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } + } + + [checkinPreferences updateWithCheckinPlistContents:checkinPlistContents]; + return checkinPreferences; +} + +- (void)migrateCheckinItemIfNeeded { + // Check for checkin in the old location, using the legacy keys + // Query the keychain for deviceID and secret + NSData *dataInOldLocation = + [self.keychain dataForService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount]; + if (dataInOldLocation) { + // Save to new location + [self.keychain setData:dataInOldLocation + forService:kFIRInstanceIDCheckinKeychainService + accessibility:NULL + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + // Remove from old location + [self.keychain removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h new file mode 100644 index 0000000..dcb5429 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A generic class to combine several handler blocks into a single block in a thread-safe manner + */ +@interface FIRInstanceIDCombinedHandler : NSObject + +- (void)addHandler:(void (^)(ResultType _Nullable result, NSError* _Nullable error))handler; +- (void (^)(ResultType _Nullable result, NSError* _Nullable error))combinedHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m new file mode 100644 index 0000000..bc6be6c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCombinedHandler.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRInstanseIDHandler)(id _Nullable result, NSError *_Nullable error); + +@interface FIRInstanceIDCombinedHandler () +@property(atomic, readonly, strong) NSMutableArray *handlers; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstanceIDCombinedHandler + +- (instancetype)init { + self = [super init]; + if (self) { + _handlers = [NSMutableArray array]; + } + return self; +} + +- (void)addHandler:(FIRInstanseIDHandler)handler { + if (!handler) { + return; + } + + @synchronized(self) { + [self.handlers addObject:handler]; + } +} + +- (FIRInstanseIDHandler)combinedHandler { + FIRInstanseIDHandler combinedHandler = nil; + + @synchronized(self) { + NSArray *handlers = [self.handlers copy]; + combinedHandler = ^(id result, NSError *error) { + for (FIRInstanseIDHandler handler in handlers) { + handler(result, error); + } + }; + } + + return combinedHandler; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h new file mode 100644 index 0000000..cd2e131 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#pragma mark - Commands + +/** + * Value included in a structured response or GCM message from IID, indicating + * an identity reset. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST; + +#pragma mark - Notifications + +/// Notification used to deliver GCM messages for InstanceID. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification; + +#pragma mark - Miscellaneous + +/// The scope used to save the IID "*" scope token. This is used for saving the +/// IID auth token that we receive from the server. This feature was never +/// implemented on the server side. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAllScopeIdentifier; +/// The scope used to save the IID "*" scope token. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultTokenScope; + +/// Subdirectory in search path directory to store InstanceID preferences. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSubDirectoryName; + +/// The key for APNS token in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSKey; + +/// The key for APNS token environment type in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + +/// The key for GMP AppID sent in registration requests. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey; + +/// The key to enable auto-register by swizzling AppDelegate's methods. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey; + +/// Error code for missing entitlements in Keychain. iOS Keychain error +/// https://forums.developer.apple.com/thread/4743 +FOUNDATION_EXPORT const int kFIRInstanceIDSecMissingEntitlementErrorCode; diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m new file mode 100644 index 0000000..81f4620 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDConstants.h" + +// Commands +NSString *const kFIRInstanceID_CMD_RST = @"RST"; + +// NOTIFICATIONS +NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenNotification = @"com.firebase.iid.notif.fcm-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification = + @"com.firebase.iid.notif.fcm-token-fail"; + +NSString *const kFIRInstanceIDIdentityInvalidatedNotification = @"com.google.iid.identity-invalid"; + +// Miscellaneous +NSString *const kFIRInstanceIDAllScopeIdentifier = @"iid-all"; +NSString *const kFIRInstanceIDDefaultTokenScope = @"*"; +NSString *const kFIRInstanceIDSubDirectoryName = @"Google/FirebaseInstanceID"; + +// Registration Options +NSString *const kFIRInstanceIDTokenOptionsAPNSKey = @"apns_token"; +NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey = @"apns_sandbox"; +NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey = @"gmp_app_id"; + +NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +// iOS Keychain error https://forums.developer.apple.com/thread/4743 +// An undocumented error code hence need to be redeclared. +const int kFIRInstanceIDSecMissingEntitlementErrorCode = -34018; diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h new file mode 100644 index 0000000..764dfe5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRInstanceIDLib_FIRInstanceIDDefines_h +#define FIRInstanceIDLib_FIRInstanceIDDefines_h + +#define _FIRInstanceID_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRInstanceID_VERBOSE_LOGGING) +#define FIRInstanceID_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRInstanceID_DEV_VERBOSE_LOG(...) \ + do { \ + } while (0) +#endif // VERBOSE_LOGGING + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRInstanceID_WEAKNAME(VAR) VAR##_weak_ + +#define FIRInstanceID_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRInstanceID_WEAKNAME(VAR) = (VAR); + +#define FIRInstanceID_STRONGIFY(VAR) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") \ + __strong __typeof__(VAR) VAR = _FIRInstanceID_WEAKNAME(VAR); \ + _Pragma("clang diagnostic pop") + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRInstanceID_L +#define _FIRInstanceID_L(v) (long)(v) +#endif + +#endif + +// Debug Assert +#ifndef _FIRInstanceIDDevAssert +// we directly invoke the NSAssert handler so we can pass on the varargs +// (NSAssert doesn't have a macro we can use that takes varargs) +#if !defined(NS_BLOCK_ASSERTIONS) +#define _FIRInstanceIDDevAssert(condition, ...) \ + do { \ + if (!(condition)) { \ + [[NSAssertionHandler currentHandler] \ + handleFailureInFunction:(NSString *)[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ + file:(NSString *)[NSString stringWithUTF8String:__FILE__] \ + lineNumber:__LINE__ \ + description:__VA_ARGS__]; \ + } \ + } while (0) +#else // !defined(NS_BLOCK_ASSERTIONS) +#define _FIRInstanceIDDevAssert(condition, ...) \ + do { \ + } while (0) +#endif // !defined(NS_BLOCK_ASSERTIONS) + +#endif // _FIRInstanceIDDevAssert diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h new file mode 100644 index 0000000..a1aa5e1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h @@ -0,0 +1,78 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDKeyPair : NSObject + +- (instancetype)init __attribute__(( + unavailable("Use -initWithPrivateKey:publicKey:publicKeyData:privateKeyData: instead."))); +; + +/** + * Initialize a new 2048 bit RSA keypair. This also stores the keypair in the Keychain + * Preferences. + * + * @param publicKey The publicKey stored in Keychain. + * @param privateKey The privateKey stored in Keychain. + * @param publicKeyData The publicKey in NSData format. + * @param privateKeyData The privateKey in NSData format. + * + * @return A new KeyPair instance with the generated public and private key. + */ +- (instancetype)initWithPrivateKey:(SecKeyRef)privateKey + publicKey:(SecKeyRef)publicKey + publicKeyData:(NSData *)publicKeyData + privateKeyData:(NSData *)privateKeyData NS_DESIGNATED_INITIALIZER; + +/** + * The public key in the RSA 20148 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's public key. + */ +@property(nonatomic, readonly, strong) NSData *publicKeyData; + +/** + * The private key in the RSA 20148 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's private key. + */ +@property(nonatomic, readonly, strong) NSData *privateKeyData; + +#pragma mark - Info + +/** + * Checks if the private and public keyPair are valid or not. + * + * @return YES if keypair is valid else NO. + */ +- (BOOL)isValid; + +/** + * The public key in the RSA 2048 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's public key. + */ +- (SecKeyRef)publicKey; + +/** + * The private key in the RSA 2048 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's private key. + */ +- (SecKeyRef)privateKey; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m new file mode 100644 index 0000000..52b27c2 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeyPair.h" + +#import + +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDKeyPair () { + SecKeyRef _privateKey; + SecKeyRef _publicKey; +} + +@property(nonatomic, readwrite, strong) NSData *publicKeyData; +@property(nonatomic, readwrite, strong) NSData *privateKeyData; +@end + +@implementation FIRInstanceIDKeyPair +- (instancetype)initWithPrivateKey:(SecKeyRef)privateKey + publicKey:(SecKeyRef)publicKey + publicKeyData:(NSData *)publicKeyData + privateKeyData:(NSData *)privateKeyData { + self = [super init]; + if (self) { + _privateKey = privateKey; + _publicKey = publicKey; + _publicKeyData = publicKeyData; + _privateKeyData = privateKeyData; + } + return self; +} + +- (void)dealloc { + if (_privateKey) { + CFRelease(_privateKey); + } + if (_publicKey) { + CFRelease(_publicKey); + } +} + +#pragma mark - Info + +- (BOOL)isValid { + return _privateKey != NULL && _publicKey != NULL; +} + +- (SecKeyRef)publicKey { + return _publicKey; +} + +- (SecKeyRef)privateKey { + return _privateKey; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h new file mode 100644 index 0000000..02c2896 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDKeyPair; + +extern NSString *const kFIRInstanceIDKeyPairSubType; + +@class FIRInstanceIDKeyPairStore; + +@interface FIRInstanceIDKeyPairStore : NSObject + +/** + * Invalidates the cached keypairs in the Keychain, if needed. The keypair metadata plist is + * checked for existence. If the plist file does not exist, it is a signal of a new installation, + * and therefore the key pairs are not valid. + * + * Returns YES if keypair has been invalidated. + */ +- (BOOL)invalidateKeyPairsIfNeeded; + +/** + * Delete the cached RSA keypair from Keychain with the given subtype. + * + * @param subtype The subtype used to cache the RSA keypair in Keychain. + * @param handler The callback handler which is invoked when the keypair deletion is + * complete, with an error if there is any. + */ +- (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype handler:(void (^)(NSError *))handler; + +/** + * Delete the plist that caches KeyPair generation timestamps. + * + * @param error The error if any while deleting the plist else nil. + * + * @return YES if the delete was successful else NO. + */ +- (BOOL)removeKeyPairCreationTimePlistWithError:(NSError **)error; + +/** + * Loads a cached KeyPair if it exists in the Keychain else generate a new + * one. If a keyPair already exists in memory this will just return that. This should + * not be called from the main thread since it could potentially lead to creating a new + * RSA-2048 bit keyPair which is an expensive operation. + * + * @param error The error, if any, while accessing the Keychain. + * + * @return A valid 2048 bit RSA key pair. + */ +- (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error; + +/** + * Check if the Keychain has any cached keypairs or not. + * + * @return YES if the Keychain has cached RSA KeyPairs else NO. + */ +- (BOOL)hasCachedKeyPairs; + +/** + * Return an identifier for the app instance. The result is a short identifier that can + * be used as a key when storing information about the app. This method will return the same + * ID as long as the application identity remains active. If the identity has been revoked or + * expired the method will generate and return a new identifier. + * + * @param error The error if any while loading the RSA KeyPair. + * + * @return The identifier, as url safe string. + */ +- (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m new file mode 100644 index 0000000..20b5cea --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m @@ -0,0 +1,530 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeyPairStore.h" + +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kFIRInstanceIDKeyPairStoreFileName = @"com.google.iid-keypair"; + +static NSString *const kFIRInstanceIDStoreKeyGenerationTime = @"cre"; + +static NSString *const kFIRInstanceIDStoreKeyPrefix = @"com.google.iid-"; +static NSString *const kFIRInstanceIDStoreKeyPublic = @"|P|"; +static NSString *const kFIRInstanceIDStoreKeyPrivate = @"|K|"; +static NSString *const kFIRInstanceIDStoreKeySubtype = @"|S|"; + +static NSString *const kFIRInstanceIDKeyPairPublicTagPrefix = @"com.google.iid.keypair.public-"; +static NSString *const kFIRInstanceIDKeyPairPrivateTagPrefix = @"com.google.iid.keypair.private-"; + +static const int kMaxMissingEntitlementErrorCount = 3; + +NSString *const kFIRInstanceIDKeyPairSubType = @""; + +// Query the key with NSData format +NSData *FIRInstanceIDKeyDataWithTag(NSString *tag) { + _FIRInstanceIDDevAssert([tag length], @"Invalid tag for keychain specified"); + if (![tag length]) { + return NULL; + } + NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, YES); + CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey]; + if (!result) { + return NULL; + } + return (__bridge NSData *)result; +} + +// Query the key given a tag +SecKeyRef FIRInstanceIDCachedKeyRefWithTag(NSString *tag) { + _FIRInstanceIDDevAssert([tag length], @"Invalid tag for keychain specified"); + if (!tag.length) { + return NULL; + } + NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, NO); + CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey]; + return (SecKeyRef)result; +} + +// Check if keypair has been migrated from the legacy to the new version +BOOL FIRInstanceIDHasMigratedKeyPair(NSString *legacyPublicKeyTag, NSString *newPublicKeyTag) { + NSData *oldPublicKeyData = FIRInstanceIDKeyDataWithTag(legacyPublicKeyTag); + NSData *newPublicKeyData = FIRInstanceIDKeyDataWithTag(newPublicKeyTag); + return [oldPublicKeyData isEqualToData:newPublicKeyData]; +} + +// The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain +// environments. +NSString *FIRInstanceIDLegacyPublicTagWithSubtype(NSString *subtype) { + NSString *prefix = kFIRInstanceIDStoreKeyPrefix; + return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPublic]; +} + +// The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain +// environments. +NSString *FIRInstanceIDLegacyPrivateTagWithSubtype(NSString *subtype) { + NSString *prefix = kFIRInstanceIDStoreKeyPrefix; + return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPrivate]; +} + +NSString *FIRInstanceIDPublicTagWithSubtype(NSString *subtype) { + static NSString *publicTag; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *mainAppBundleID = FIRInstanceIDAppIdentifier(); + publicTag = + [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPublicTagPrefix, mainAppBundleID]; + }); + return publicTag; +} + +NSString *FIRInstanceIDPrivateTagWithSubtype(NSString *subtype) { + static NSString *privateTag; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *mainAppBundleID = FIRInstanceIDAppIdentifier(); + privateTag = + [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPrivateTagPrefix, mainAppBundleID]; + }); + return privateTag; +} + +NSString *FIRInstanceIDCreationTimeKeyWithSubtype(NSString *subtype) { + return [NSString stringWithFormat:@"%@%@%@", subtype, kFIRInstanceIDStoreKeySubtype, + kFIRInstanceIDStoreKeyGenerationTime]; +} + +@interface FIRInstanceIDKeyPairStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair; +@property(nonatomic, readwrite, assign) NSInteger keychainEntitlementsErrorCount; + +@end + +@implementation FIRInstanceIDKeyPairStore + +- (instancetype)init { + self = [super init]; + if (self) { + NSString *fileName = [[self class] keyStoreFileName]; + _plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:fileName + subDirectory:kFIRInstanceIDSubDirectoryName]; + } + return self; +} + +- (BOOL)invalidateKeyPairsIfNeeded { + // Currently keypairs are always invalidated if self.plist is missing. This normally indicates + // a fresh install (or an uninstall/reinstall). In those situations the key pairs should be + // deleted. + // NOTE: Although this class refers to multiple key pairs, with different subtypes, in practice + // only a single subtype is currently supported. (b/64906549) + if (![self.plist doesFileExist]) { + // A fresh install, clear all the key pairs in the key chain. Do not perform migration as all + // key pairs are gone. + [self deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType handler:nil]; + return YES; + } + // Not a fresh install, perform migration at early state. + [self migrateKeyPairCacheIfNeededWithHandler:nil]; + return NO; +} + +- (BOOL)hasCachedKeyPairs { + NSError *error; + if ([self cachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:&error] == nil) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore000, + @"Failed to get the cached keyPair %@", error); + } + error = nil; + [self removeKeyPairCreationTimePlistWithError:&error]; + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore001, + @"Failed to remove keyPair creationTime plist %@", error); + } + return NO; + } + return YES; +} + +- (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error { + // Load the keyPair from Keychain (or generate a key pair, if this is the first run of the app). + FIRInstanceIDKeyPair *keyPair = [self loadKeyPairWithError:error]; + if (!keyPair) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair, + @"Keypair could not be loaded from Keychain. Error: %@", (*error)); + return nil; + } + + if (error) { + *error = nil; + } + NSString *appIdentity = FIRInstanceIDAppIdentity(keyPair); + if (!appIdentity.length) { + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + } + return appIdentity; +} + +- (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error { + // In case we call this from different threads we don't want to generate or fetch the + // keyPair multiple times. Once we have a keyPair in the cache it would mostly be used + // from there. + @synchronized(self) { + if ([self.keyPair isValid]) { + return self.keyPair; + } + + if (self.keychainEntitlementsErrorCount >= kMaxMissingEntitlementErrorCount) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore002, + @"Keychain not accessible, Entitlements missing error (-34018). " + @"Will not check token in cache."); + return nil; + } + + if (!self.keyPair) { + self.keyPair = [self validCachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:error]; + } + + if ((*error).code == kFIRInstanceIDSecMissingEntitlementErrorCode) { + self.keychainEntitlementsErrorCount++; + } + + if (!self.keyPair) { + self.keyPair = [self generateAndSaveKeyWithSubtype:kFIRInstanceIDKeyPairSubType + creationTime:FIRInstanceIDCurrentTimestampInSeconds() + error:error]; + } + } + return self.keyPair; +} + +// TODO(chliangGoogle: Remove subtype support, as it's not being used. +- (FIRInstanceIDKeyPair *)generateAndSaveKeyWithSubtype:(NSString *)subtype + creationTime:(int64_t)creationTime + error:(NSError **)error { + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype); + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype); + FIRInstanceIDKeyPair *keyPair = + [[FIRInstanceIDKeychain sharedInstance] generateKeyPairWithPrivateTag:privateKeyTag + publicTag:publicKeyTag]; + + if (![keyPair isValid]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore003, + @"Unable to generate keypair."); + return nil; + } + + NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype); + NSDictionary *keyPairData = @{creationTimeKey : @(creationTime)}; + + if (error) { + *error = nil; + } + NSMutableDictionary *allKeyPairs = [[self.plist contentAsDictionary] mutableCopy]; + if (allKeyPairs.count) { + [allKeyPairs addEntriesFromDictionary:keyPairData]; + } else { + allKeyPairs = [keyPairData mutableCopy]; + } + if (![self.plist writeDictionary:allKeyPairs error:error]) { + [FIRInstanceIDKeyPairStore deleteKeyPairWithPrivateTag:privateKeyTag + publicTag:publicKeyTag + handler:nil]; + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore004, + @"Failed to save keypair data to plist %@", error ? *error : @""); + return nil; + } + + return keyPair; +} + +- (FIRInstanceIDKeyPair *)validCachedKeyPairWithSubtype:(NSString *)subtype + error:(NSError **)error { + // On a new install (or if the ID was deleted), the plist will be missing, which should trigger + // a reset of the key pairs in Keychain (if they exist). + NSDictionary *allKeyPairs = [self.plist contentAsDictionary]; + NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype); + + if (allKeyPairs[creationTimeKey] > 0) { + return [self cachedKeyPairWithSubtype:subtype error:error]; + } else { + // There is no need to reset keypair again here as FIRInstanceID init call is always + // going to be ahead of this call, which already trigger keypair reset if it's new install + FIRInstanceIDErrorCode code = kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime; + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:code]; + } + return nil; + } +} + +- (FIRInstanceIDKeyPair *)cachedKeyPairWithSubtype:(NSString *)subtype + error:(NSError *__autoreleasing *)error { + // base64 encoded keys + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype); + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype); + return [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:privateKeyTag + publicKeyTag:publicKeyTag + error:error]; +} + ++ (FIRInstanceIDKeyPair *)keyPairForPrivateKeyTag:(NSString *)privateKeyTag + publicKeyTag:(NSString *)publicKeyTag + error:(NSError *__autoreleasing *)error { + _FIRInstanceIDDevAssert([privateKeyTag length] && [publicKeyTag length], + @"Invalid tags for keypair"); + if (![privateKeyTag length] || ![publicKeyTag length]) { + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPairTags]; + } + return nil; + } + + SecKeyRef privateKeyRef = FIRInstanceIDCachedKeyRefWithTag(privateKeyTag); + SecKeyRef publicKeyRef = FIRInstanceIDCachedKeyRefWithTag(publicKeyTag); + + if (!privateKeyRef || !publicKeyRef) { + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeMissingKeyPair]; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPair000, + @"No keypair info is found with tag %@", privateKeyTag); + return nil; + } + + NSData *publicKeyData = FIRInstanceIDKeyDataWithTag(publicKeyTag); + NSData *privateKeyData = FIRInstanceIDKeyDataWithTag(privateKeyTag); + + FIRInstanceIDKeyPair *keyPair = [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKeyRef + publicKey:publicKeyRef + publicKeyData:publicKeyData + privateKeyData:privateKeyData]; + return keyPair; +} + +// Migrates from keypair saved under legacy keys (hardcoded value) to dynamic keys (stable, but +// unique for the app's bundle id +- (void)migrateKeyPairCacheIfNeededWithHandler:(void (^)(NSError *error))handler { + // Attempt to load keypair using legacy keys + NSString *legacyPublicKeyTag = + FIRInstanceIDLegacyPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType); + NSString *legacyPrivateKeyTag = + FIRInstanceIDLegacyPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType); + NSError *error; + FIRInstanceIDKeyPair *keyPair = + [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:legacyPrivateKeyTag + publicKeyTag:legacyPublicKeyTag + error:&error]; + if (![keyPair isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair, + @"There's no legacy keypair so no need to do migration."); + if (handler) { + handler(nil); + } + return; + } + + // Check whether migration already done. + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType); + if (FIRInstanceIDHasMigratedKeyPair(legacyPublicKeyTag, publicKeyTag)) { + if (handler) { + handler(nil); + } + return; + } + + // Also cache locally since we are sure to use the migrated key pair. + self.keyPair = keyPair; + + // Either new key pair doesn't exist or it's different than legacy key pair, start the migration. + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType); + [self updateKeyRef:keyPair.publicKey + withTag:publicKeyTag + handler:^(NSError *error) { + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairMigrationError, + @"Unable to migrate key pair from legacy ones."); + } + [self updateKeyRef:keyPair.privateKey + withTag:privateKeyTag + handler:^(NSError *error) { + if (error) { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeKeyPairMigrationError, + @"Unable to migrate key pair from legacy ones."); + return; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeKeyPairMigrationSuccess, + @"Successfully migrated the key pair from legacy ones."); + if (handler) { + handler(error); + } + }]; + }]; +} + +// Used for migrating from legacy tags to updated tags. The legacy keychain is not deleted for +// backward compatibility. +// TODO(chliangGoogle) Delete the legacy keychain when GCM is fully deprecated. +- (void)updateKeyRef:(SecKeyRef)keyRef + withTag:(NSString *)tag + handler:(void (^)(NSError *error))handler { + NSData *updatedTagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + // Always delete the old keychain before adding a new one to avoid conflicts. + NSDictionary *deleteQuery = @{ + (__bridge id)kSecAttrApplicationTag : updatedTagData, + (__bridge id)kSecClass : (__bridge id)kSecClassKey, + (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA, + (__bridge id)kSecReturnRef : @(YES), + }; + + [[FIRInstanceIDKeychain sharedInstance] + removeItemWithQuery:deleteQuery + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + NSDictionary *addQuery = @{ + (__bridge id)kSecAttrApplicationTag : updatedTagData, + (__bridge id)kSecClass : (__bridge id)kSecClassKey, + (__bridge id)kSecValueRef : (__bridge id)keyRef, + (__bridge id) + kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + [[FIRInstanceIDKeychain sharedInstance] addItemWithQuery:addQuery + handler:^(NSError *addError) { + if (handler) { + handler(addError); + } + }]; + }]; +} + +- (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype + handler:(void (^)(NSError *error))handler { + NSDictionary *allKeyPairs = [self.plist contentAsDictionary]; + + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype); + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype); + NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype); + + // remove the creation time + if (allKeyPairs[creationTimeKey] > 0) { + NSMutableDictionary *newKeyPairs = [NSMutableDictionary dictionaryWithDictionary:allKeyPairs]; + [newKeyPairs removeObjectForKey:creationTimeKey]; + + NSError *plistError; + if (![self.plist writeDictionary:newKeyPairs error:&plistError]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore006, + @"Unable to remove keypair creation time from plist %@", plistError); + } + } + + [FIRInstanceIDKeyPairStore + deleteKeyPairWithPrivateTag:privateKeyTag + publicTag:publicKeyTag + handler:^(NSError *error) { + // Delete legacy key pairs from GCM/FCM If they exist. All key pairs + // should be deleted when app is newly installed. + NSString *legacyPublicKeyTag = + FIRInstanceIDLegacyPublicTagWithSubtype(subtype); + NSString *legacyPrivateKeyTag = + FIRInstanceIDLegacyPrivateTagWithSubtype(subtype); + [FIRInstanceIDKeyPairStore + deleteKeyPairWithPrivateTag:legacyPrivateKeyTag + publicTag:legacyPublicKeyTag + handler:nil]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore007, + @"Unable to remove RSA keypair, error: %@", + error); + if (handler) { + handler(error); + } + } else { + self.keyPair = nil; + if (handler) { + handler(nil); + } + } + }]; +} + ++ (void)deleteKeyPairWithPrivateTag:(NSString *)privateTag + publicTag:(NSString *)publicTag + handler:(void (^)(NSError *))handler { + NSDictionary *queryPublicKey = FIRInstanceIDKeyPairQuery(publicTag, NO, NO); + NSDictionary *queryPrivateKey = FIRInstanceIDKeyPairQuery(privateTag, NO, NO); + + // Always remove public key first because it is the key we generate IID. + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:queryPublicKey + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + [[FIRInstanceIDKeychain sharedInstance] + removeItemWithQuery:queryPrivateKey + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + }]; +} + +- (BOOL)removeKeyPairCreationTimePlistWithError:(NSError *__autoreleasing *)error { + if (![self.plist deleteFile:error]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore008, + @"Unable to delete keypair creation times plist"); + return NO; + } + return YES; +} + ++ (NSString *)keyStoreFileName { + return kFIRInstanceIDKeyPairStoreFileName; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h new file mode 100644 index 0000000..b8baa6a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDKeyPair; + +/** + * A web-safe base64 encoded string with no padding. + * + * @param data The data to encode. + * + * @return A web-safe base 64 encoded string with no padding. + */ +FOUNDATION_EXPORT NSString *FIRInstanceIDWebSafeBase64(NSData *data); + +FOUNDATION_EXPORT NSData *FIRInstanceIDSHA1(NSData *data); + +FOUNDATION_EXPORT NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag, + BOOL addReturnAttr, + BOOL returnData); + +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair); diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m new file mode 100644 index 0000000..3298752 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m @@ -0,0 +1,84 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeyPairUtilities.h" + +#import + +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStringEncoding.h" + +NSString *FIRInstanceIDWebSafeBase64(NSData *data) { + // Websafe encoding with no padding. + FIRInstanceIDStringEncoding *encoding = + [FIRInstanceIDStringEncoding rfc4648Base64WebsafeStringEncoding]; + [encoding setDoPad:NO]; + return [encoding encode:data]; +} + +NSData *FIRInstanceIDSHA1(NSData *data) { + unsigned int outputLength = CC_SHA1_DIGEST_LENGTH; + unsigned char output[outputLength]; + unsigned int length = (unsigned int)[data length]; + + CC_SHA1(data.bytes, length, output); + return [NSMutableData dataWithBytes:output length:outputLength]; +} + +NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag, BOOL addReturnAttr, BOOL returnData) { + NSMutableDictionary *queryKey = [NSMutableDictionary dictionary]; + NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + queryKey[(__bridge id)kSecClass] = (__bridge id)kSecClassKey; + queryKey[(__bridge id)kSecAttrApplicationTag] = tagData; + queryKey[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA; + if (addReturnAttr) { + if (returnData) { + queryKey[(__bridge id)kSecReturnData] = @(YES); + } else { + queryKey[(__bridge id)kSecReturnRef] = @(YES); + } + } + return queryKey; +} + +NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair) { + // An Instance-ID is a 64 bit (8 byte) integer with a fixed 4-bit header of 0111 (=^ 0x7). + // The variable 60 bits are obtained by truncating the SHA1 of the app-instance's public key. + SecKeyRef publicKeyRef = [keyPair publicKey]; + if (!publicKeyRef) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPair002, + @"Unable to create a valid asymmetric crypto key"); + return nil; + } + NSData *publicKeyData = keyPair.publicKeyData; + NSData *publicKeySHA1 = FIRInstanceIDSHA1(publicKeyData); + + const uint8_t *bytes = publicKeySHA1.bytes; + NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1]; + + uint8_t b0 = bytes[0]; + // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0 + // and then adding 0x70 to it. + b0 = 0x70 + (0xF & b0); + // failsafe should give you back b0 itself + b0 = (b0 & 0xFF); + [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0]; + NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))]; + return FIRInstanceIDWebSafeBase64(data); +} diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h new file mode 100644 index 0000000..0bd2a49 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h @@ -0,0 +1,76 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/* The Keychain error domain */ +extern NSString *const kFIRInstanceIDKeychainErrorDomain; + +@class FIRInstanceIDKeyPair; + +/* + * Wrapping the keychain operations in a serialize queue. This is to avoid keychain operation + * blocking main queue. + */ +@interface FIRInstanceIDKeychain : NSObject + +/** + * FIRInstanceIDKeychain. + * + * @return A shared instance of FIRInstanceIDKeychain. + */ ++ (instancetype)sharedInstance; + +/** + * Get keychain items matching the given a query. + * + * @param keychainQuery The keychain query. + * + * @return An CFTypeRef result matching the provided inputs. + */ +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery; + +/** + * Remove the cached items from the keychain matching the query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the remove operation is + * complete, with an error if there is any. + */ +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *error))handler; + +/** + * Add the item with a given query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the add operation is + * complete, with an error if there is any. + */ +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler; + +#pragma mark - Keypair +/** + * Generate a public/private key pair given their tags. + * + * @param privateTag The private tag associated with the private key. + * @param publicTag The public tag associated with the public key. + * + * @return A new FIRInstanceIDKeyPair object. + */ +- (FIRInstanceIDKeyPair *)generateKeyPairWithPrivateTag:(NSString *)privateTag + publicTag:(NSString *)publicTag; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m new file mode 100644 index 0000000..81c7372 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m @@ -0,0 +1,174 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeychain.h" + +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDLogger.h" + +NSString *const kFIRInstanceIDKeychainErrorDomain = @"com.google.iid"; + +static const NSUInteger kRSA2048KeyPairSize = 2048; + +@interface FIRInstanceIDKeychain () { + dispatch_queue_t _keychainOperationQueue; +} + +@end + +@implementation FIRInstanceIDKeychain + ++ (instancetype)sharedInstance { + static FIRInstanceIDKeychain *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRInstanceIDKeychain alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _keychainOperationQueue = + dispatch_queue_create("com.google.FirebaseInstanceID.Keychain", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery { + __block SecKeyRef keyRef = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDKeychainReadItemError, + @"Info is not found in Keychain. OSStatus: %d. Keychain query: %@", + (int)status, keychainQuery); + } + }); + return keyRef; +} + +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery + handler:(void (^)(NSError *error))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery); + if (status != noErr) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDKeychainDeleteItemError, + @"Couldn't delete item from Keychain OSStatus: %d with the keychain query %@", + (int)status, keychainQuery); + } + + if (handler) { + NSError *error; + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); + + if (handler) { + NSError *error; + if (status != noErr) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainAddItemError, + @"Couldn't add item to Keychain OSStatus: %d", (int)status); + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (FIRInstanceIDKeyPair *)generateKeyPairWithPrivateTag:(NSString *)privateTag + publicTag:(NSString *)publicTag { + // TODO(chliangGoogle) this is called by appInstanceID, which is an internal API used by other + // Firebase teams, will see if we can make it async. + NSData *publicTagData = [publicTag dataUsingEncoding:NSUTF8StringEncoding]; + NSData *privateTagData = [privateTag dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary *privateKeyAttr = @{ + (__bridge id)kSecAttrIsPermanent : @YES, + (__bridge id)kSecAttrApplicationTag : privateTagData, + (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair Private Key", + (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + + NSDictionary *publicKeyAttr = @{ + (__bridge id)kSecAttrIsPermanent : @YES, + (__bridge id)kSecAttrApplicationTag : publicTagData, + (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair Public Key", + (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + + NSDictionary *keyPairAttributes = @{ + (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA, + (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair", + (__bridge id)kSecAttrKeySizeInBits : @(kRSA2048KeyPairSize), + (__bridge id)kSecPrivateKeyAttrs : privateKeyAttr, + (__bridge id)kSecPublicKeyAttrs : publicKeyAttr, + }; + + __block SecKeyRef privateKey = NULL; + __block SecKeyRef publicKey = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + // SecKeyGeneratePair does not allow you to set kSetAttrAccessible on the keys. We need the keys + // to be accessible even when the device is locked (i.e. app is woken up during a push + // notification, or some background refresh). + OSStatus status = + SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttributes, &publicKey, &privateKey); + if (status != noErr || publicKey == NULL || privateKey == NULL) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainCreateKeyPairError, + @"Couldn't create keypair from Keychain OSStatus: %d", + (int)status); + } + }); + // Extract the actual public and private key data from the Keychain + NSDictionary *publicKeyDataQuery = FIRInstanceIDKeyPairQuery(publicTag, YES, YES); + NSDictionary *privateKeyDataQuery = FIRInstanceIDKeyPairQuery(privateTag, YES, YES); + + NSData *publicKeyData = (__bridge NSData *)[self itemWithQuery:publicKeyDataQuery]; + NSData *privateKeyData = (__bridge NSData *)[self itemWithQuery:privateKeyDataQuery]; + + return [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKey + publicKey:publicKey + publicKeyData:publicKeyData + privateKeyData:privateKeyData]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h new file mode 100644 index 0000000..ab93976 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRIMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRInstanceIDLoggerInfo + +// Convenience macros that log to the shared GTMLogger instance. These macros +// are how users should typically log to FIRInstanceIDLogger. +#define FIRInstanceIDLoggerDebug(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerInfo(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerNotice(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerWarning(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerError(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRInstanceIDLoggerInfo) + +@interface FIRInstanceIDLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared GTMLogger used exclusively + * for InstanceID log messages. + * @return the shared GTMLogger instance + */ +FIRInstanceIDLogger *FIRInstanceIDSharedLogger(void); diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m new file mode 100644 index 0000000..2600d3b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDLogger.h" + +#import + +// Re-definition of FIRLogger service, as it is not included in :FIRAppHeaders target +NSString *const kFIRInstanceIDLoggerService = @"[Firebase/InstanceID]"; + +@implementation FIRInstanceIDLogger + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRInstanceIDMessageCode)messageCode { + return [NSString stringWithFormat:@"I-IID%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRInstanceIDLogger *FIRInstanceIDSharedLogger() { + static dispatch_once_t onceToken; + static FIRInstanceIDLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [[FIRInstanceIDLogger alloc] init]; + }); + + return logger; +} diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h new file mode 100644 index 0000000..d1f2634 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h @@ -0,0 +1,183 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDCheckinStore; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDTokenStore; + +@class FIRInstanceIDStore; +@protocol FIRInstanceIDStoreDelegate + +/** + * This is called when the store has decided to invalide its tokens associated with the + * previous checkin credentials. After deleting the tokens locally, it calls this method + * to notify the delegate of the change. If possible, the delegate should use this time + * to request the invalidation of the tokens on the server as well. + */ +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +@end + +/** + * Used to persist the InstanceID tokens. This is also used to cache the Checkin + * credentials. The store also checks for stale entries in the store and + * let's us know if things in the store are stale or not. It does not however + * acts on stale entries in anyway. + */ +@interface FIRInstanceIDStore : NSObject + +/** + * The delegate set in the initializer which is notified of changes in the store. + */ +@property(nonatomic, readonly, weak) NSObject *delegate; + +- (instancetype)init __attribute__((unavailable("Use initWithDelegate: instead."))); + +/** + * Initialize a default store to persist InstanceID tokens and options. + * + * @param delegate The delegate with which to be notified of changes in the store. + * @return Store to persist InstanceID tokens. + */ +- (instancetype)initWithDelegate:(NSObject *)delegate; + +/** + * Initialize a store with the token store used to persist tokens, and a checkin store. + * Used for testing. + * + * @param checkinStore Persistent store that persists checkin preferences. + * @param tokenStore Persistent store that persists tokens. + * + * @return Store to persist InstanceID tokens and options. + */ +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Save +/** + * Save the instanceID token info to the store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo handler:(void (^)(NSError *))handler; + +#pragma mark - Get + +/** + * Get the cached token info. + * + * @param authorizedEntity The authorized entity for which we want the token. + * @param scope The scope for which we want the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * returns nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Delete + +/** + * Remove the cached token for a given authorizedEntity and scope. If the token was never + * cached or deleted from the cache before this is a no-op. + * + * @param authorizedEntity The authorizedEntity for the cached token. + * @param scope The scope for the cached token + */ +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Removes all cached tokens from the persistent store. In case deleting the cached tokens + * fails we try to delete the backup excluded plist that stores the tokens. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + * + */ +- (void)removeAllCachedTokensWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Persisting Checkin Preferences + +/** + * Save the checkin preferences + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(nullable void (^)(NSError *error))handler; + +/** + * Return the cached checkin preferences. + * + * @return Checkin preferences. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Remove the cached checkin preferences from the store. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Standard Directory sub-directory + +/** + * Check if supported directory has InstanceID subdirectory + * + * @return YES if the Application Support directory has InstanceID subdirectory else NO. + */ ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName; + +/** + * Create InstanceID subdirectory in Application support directory. + * + * @return YES if the subdirectory was created successfully else NO. + */ ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName; + +/** + * Removes Application Support subdirectory for InstanceID. + * + * @param error The error object if any while trying to delete the sub-directory. + * + * @return YES if the deletion was successful else NO. + */ ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m new file mode 100644 index 0000000..1c7a0d0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDStore.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinStore.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenStore.h" +#import "FIRInstanceIDVersionUtilities.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kCheckinFileName = @"g-checkin"; + +// APNS token (use the old key value i.e. with prefix GMS) +static NSString *const kFIRInstanceIDLibraryVersion = @"GMSInstanceID-version"; + +@interface FIRInstanceIDStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinStore *checkinStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore; + +@end + +@implementation FIRInstanceIDStore + +- (instancetype)initWithDelegate:(NSObject *)delegate { + FIRInstanceIDCheckinStore *checkinStore = [[FIRInstanceIDCheckinStore alloc] + initWithCheckinPlistFileName:kCheckinFileName + subDirectoryName:kFIRInstanceIDSubDirectoryName]; + + FIRInstanceIDTokenStore *tokenStore = [FIRInstanceIDTokenStore defaultStore]; + + return [self initWithCheckinStore:checkinStore tokenStore:tokenStore delegate:delegate]; +} + +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate { + self = [super init]; + if (self) { + _checkinStore = checkinStore; + _tokenStore = tokenStore; + _delegate = delegate; + [self resetCredentialsIfNeeded]; + } + return self; +} + +#pragma mark - Upgrades + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + ++ (NSString *)pathForSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[ dirPath, subDirectoryName ]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore000, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore001, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error { + if ([self hasSubDirectory:subDirectoryName]) { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return [[NSFileManager defaultManager] removeItemAtPath:subDirectoryPath error:error]; + } + } + return YES; +} + +/** + * Reset the keychain preferences if the app had been deleted earlier and then reinstalled. + * Keychain preferences are not cleared in the above scenario so explicitly clear them. + * + * In case of an iCloud backup and restore the Keychain preferences should already be empty + * since the Keychain items are marked with `*BackupThisDeviceOnly`. + */ +- (void)resetCredentialsIfNeeded { + BOOL checkinPlistExists = [self.checkinStore hasCheckinPlist]; + // Checkin info existed in backup excluded plist. Should not be a fresh install. + if (checkinPlistExists) { + // FCM user can still have the old version of checkin, migration should only happen once. + [self.checkinStore migrateCheckinItemIfNeeded]; + return; + } + + // reset checkin in keychain if a fresh install. + // set the old checkin preferences to unregister pre-registered tokens + FIRInstanceIDCheckinPreferences *oldCheckinPreferences = + [self.checkinStore cachedCheckinPreferences]; + + if (oldCheckinPreferences) { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeStore002, + @"Removed cached checkin preferences from Keychain because this is a fresh install."); + } else { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeStore003, + @"Couldn't remove cached checkin preferences for a fresh install. Error: %@", error); + } + if (oldCheckinPreferences.deviceID.length && oldCheckinPreferences.secretToken.length) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore006, + @"App reset detected. Will delete server registrations."); + // We don't really need to delete old FCM tokens created via IID auth tokens since + // those tokens are already hashed by APNS token as the has so creating a new + // token should automatically delete the old-token. + [self.delegate store:self didDeleteFCMScopedTokensForCheckin:oldCheckinPreferences]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore009, + @"App reset detected but no valid checkin auth preferences found." + @" Will not delete server registrations."); + } + }]; + } +} + +#pragma mark - Get + +- (FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + // TODO(chliangGoogle): If we don't have the token plist we should delete all the tokens from + // the keychain. This is because not having the plist signifies a backup and restore operation. + // In case the keychain has any tokens these would now be stale and therefore should be + // deleted. + if (![authorizedEntity length] || ![scope length]) { + return nil; + } + FIRInstanceIDTokenInfo *info = [self.tokenStore tokenInfoWithAuthorizedEntity:authorizedEntity + scope:scope]; + return info; +} + +- (NSArray *)cachedTokenInfos { + return [self.tokenStore cachedTokenInfos]; +} + +#pragma mark - Save + +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *error))handler { + [self.tokenStore saveTokenInfo:tokenInfo handler:handler]; +} + +#pragma mark - Delete + +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + if (![authorizedEntity length] || ![scope length]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore012, + @"Will not delete token with invalid entity: %@, scope: %@", + authorizedEntity, scope); + return; + } + [self.tokenStore removeTokenWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)removeAllCachedTokensWithHandler:(void (^)(NSError *error))handler { + [self.tokenStore removeAllTokensWithHandler:handler]; +} + +#pragma mark - FIRInstanceIDCheckinCache protocol + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + [self.checkinStore saveCheckinPreferences:preferences handler:handler]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.checkinStore cachedCheckinPreferences]; +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *))handler { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (handler) { + handler(error); + } + }]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h new file mode 100644 index 0000000..8f2f369 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h @@ -0,0 +1,66 @@ +// +// GTMStringEncoding.h +// +// Copyright 2010 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import + +// A generic class for arbitrary base-2 to 128 string encoding and decoding. +@interface FIRInstanceIDStringEncoding : NSObject { + @private + NSData *charMapData_; + char *charMap_; + int reverseCharMap_[128]; + int shift_; + unsigned int mask_; + BOOL doPad_; + char paddingChar_; + int padLen_; +} + ++ (id)rfc4648Base64WebsafeStringEncoding; + +// Create a new, autoreleased GTMStringEncoding object with the given string, +// as described below. ++ (id)stringEncodingWithString:(NSString *)string; + +// Initialize a new GTMStringEncoding object with the string. +// +// The length of the string must be a power of 2, at least 2 and at most 128. +// Only 7-bit ASCII characters are permitted in the string. +// +// These characters are the canonical set emitted during encoding. +// If the characters have alternatives (e.g. case, easily transposed) then use +// addDecodeSynonyms: to configure them. +- (id)initWithString:(NSString *)string; + +// Indicates whether padding is performed during encoding. +- (BOOL)doPad; +- (void)setDoPad:(BOOL)doPad; + +// Sets the padding character to use during encoding. +- (void)setPaddingChar:(char)c; + +// Encode a raw binary buffer to a 7-bit ASCII string. +- (NSString *)encode:(NSData *)data; + +// Decode a 7-bit ASCII string to a raw binary buffer. +- (NSData *)decode:(NSString *)string; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m new file mode 100644 index 0000000..64b6d3e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m @@ -0,0 +1,202 @@ +#import "FIRInstanceIDDefines.h" + +// +// FIRInstanceIDStringEncoding.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import "FIRInstanceIDStringEncoding.h" + +enum { kUnknownChar = -1, kPaddingChar = -2, kIgnoreChar = -3 }; + +@implementation FIRInstanceIDStringEncoding + ++ (id)rfc4648Base64WebsafeStringEncoding { + FIRInstanceIDStringEncoding *ret = [self + stringEncodingWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"]; + + [ret setPaddingChar:'=']; + [ret setDoPad:YES]; + return ret; +} + +static inline int lcm(int a, int b) { + for (int aa = a, bb = b;;) { + if (aa == bb) + return aa; + else if (aa < bb) + aa += a; + else + bb += b; + } +} + ++ (id)stringEncodingWithString:(NSString *)string { + return [[FIRInstanceIDStringEncoding alloc] initWithString:string]; +} + +- (id)initWithString:(NSString *)string { + if ((self = [super init])) { + charMapData_ = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (!charMapData_) { + // Unable to convert string to ASCII + return nil; + } + charMap_ = (char *)[charMapData_ bytes]; + NSUInteger length = [charMapData_ length]; + if (length < 2 || length > 128 || length & (length - 1)) { + // Length not a power of 2 between 2 and 128 + return nil; + } + + memset(reverseCharMap_, kUnknownChar, sizeof(reverseCharMap_)); + for (unsigned int i = 0; i < length; i++) { + if (reverseCharMap_[(int)charMap_[i]] != kUnknownChar) { + // Duplicate character at |i| + return nil; + } + reverseCharMap_[(int)charMap_[i]] = i; + } + + for (NSUInteger i = 1; i < length; i <<= 1) shift_++; + mask_ = (1 << shift_) - 1; + padLen_ = lcm(8, shift_) / shift_; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"", 1 << shift_, charMapData_]; +} + +- (BOOL)doPad { + return doPad_; +} + +- (void)setDoPad:(BOOL)doPad { + doPad_ = doPad; +} + +- (void)setPaddingChar:(char)c { + paddingChar_ = c; + reverseCharMap_[(int)c] = kPaddingChar; +} + +- (NSString *)encode:(NSData *)inData { + NSUInteger inLen = [inData length]; + if (inLen <= 0) { + // Empty input + return @""; + } + unsigned char *inBuf = (unsigned char *)[inData bytes]; + NSUInteger inPos = 0; + + NSUInteger outLen = (inLen * 8 + shift_ - 1) / shift_; + if (doPad_) { + outLen = ((outLen + padLen_ - 1) / padLen_) * padLen_; + } + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + unsigned int buffer = inBuf[inPos++]; + int bitsLeft = 8; + while (bitsLeft > 0 || inPos < inLen) { + if (bitsLeft < shift_) { + if (inPos < inLen) { + buffer <<= 8; + buffer |= (inBuf[inPos++] & 0xff); + bitsLeft += 8; + } else { + int pad = shift_ - bitsLeft; + buffer <<= pad; + bitsLeft += pad; + } + } + unsigned int idx = (buffer >> (bitsLeft - shift_)) & mask_; + bitsLeft -= shift_; + outBuf[outPos++] = charMap_[idx]; + } + + if (doPad_) { + while (outPos < outLen) outBuf[outPos++] = paddingChar_; + } + + _FIRInstanceIDDevAssert(outPos == outLen, @"Underflowed output buffer"); + [outData setLength:outPos]; + + return [[NSString alloc] initWithData:outData encoding:NSASCIIStringEncoding]; +} + +- (NSData *)decode:(NSString *)inString { + char *inBuf = (char *)[inString cStringUsingEncoding:NSASCIIStringEncoding]; + if (!inBuf) { + // Unable to convert buffer to ASCII + return nil; + } + NSUInteger inLen = strlen(inBuf); + + NSUInteger outLen = inLen * shift_ / 8; + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + int buffer = 0; + int bitsLeft = 0; + BOOL expectPad = NO; + for (NSUInteger i = 0; i < inLen; i++) { + int val = reverseCharMap_[(int)inBuf[i]]; + switch (val) { + case kIgnoreChar: + break; + case kPaddingChar: + expectPad = YES; + break; + case kUnknownChar: + // Unexpected data at input pos |i| + return nil; + default: + if (expectPad) { + // Expected further padding characters + return nil; + } + buffer <<= shift_; + buffer |= val & mask_; + bitsLeft += shift_; + if (bitsLeft >= 8) { + outBuf[outPos++] = (unsigned char)(buffer >> (bitsLeft - 8)); + bitsLeft -= 8; + } + break; + } + } + + if (bitsLeft && buffer & ((1 << bitsLeft) - 1)) { + // Incomplete trailing data + return nil; + } + + // Shorten buffer if needed due to padding chars + _FIRInstanceIDDevAssert(outPos <= outLen, @"Overflowed buffer"); + [outData setLength:outPos]; + + return outData; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h new file mode 100644 index 0000000..58368d0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenDeleteOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(nullable NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(nullable FIRInstanceIDKeyPair *)keyPair + action:(FIRInstanceIDTokenAction)action; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m new file mode 100644 index 0000000..365f321 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m @@ -0,0 +1,120 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenDeleteOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +@implementation FIRInstanceIDTokenDeleteOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair + action:(FIRInstanceIDTokenAction)action { + self = [super initWithAction:action + forAuthorizedEntity:authorizedEntity + scope:scope + options:nil + checkinPreferences:checkinPreferences + keyPair:keyPair]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + NSMutableURLRequest *request = [FIRInstanceIDTokenOperation requestWithAuthHeader:authHeader]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [FIRInstanceIDTokenOperation standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"delete" value:@"true"]]; + if (self.action == FIRInstanceIDTokenActionDeleteTokenAndIID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"iid-operation" + value:@"delete"]]; + } + if (self.authorizedEntity) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + } + // Typically we include our public key-signed url items, but in some cases (like deleting all FCM + // tokens), we don't. + if (self.keyPair != nil) { + [queryItems addObjectsFromArray:[self queryItemsWithKeyPair:self.keyPair]]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest, + @"Unregister request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError, + @"Device unregister HTTP fetch error. Error code: %ld", + _FIRInstanceID_L(error.code)); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + if (![dataResponse hasPrefix:@"deleted="] && ![dataResponse hasPrefix:@"token="]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse, + @"Invalid unregister response %@", response); + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded token:nil error:nil]; +} +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h new file mode 100644 index 0000000..87be60f --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseUserAgentKey; + +@interface FIRInstanceIDTokenFetchOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair; + +@end +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m new file mode 100644 index 0000000..b545c24 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m @@ -0,0 +1,205 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenFetchOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +#import + +// We can have a static int since this error should theoretically only +// happen once (for the first time). If it repeats there is something +// else that is wrong. +static int phoneRegistrationErrorRetryCount = 0; +static const int kMaxPhoneRegistrationErrorRetryCount = 10; +NSString *const kFIRInstanceIDFirebaseUserAgentKey = @"X-firebase-client"; + +@implementation FIRInstanceIDTokenFetchOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair { + self = [super initWithAction:FIRInstanceIDTokenActionFetch + forAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + keyPair:keyPair]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + NSMutableURLRequest *request = [[self class] requestWithAuthHeader:authHeader]; + NSString *checkinVersionInfo = self.checkinPreferences.versionInfo; + [request setValue:checkinVersionInfo forHTTPHeaderField:@"info"]; + [request setValue:[FIRApp firebaseUserAgent] + forHTTPHeaderField:kFIRInstanceIDFirebaseUserAgentKey]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [[self class] standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-subtype" + value:self.authorizedEntity]]; + + [queryItems addObjectsFromArray:[self queryItemsWithKeyPair:self.keyPair]]; + + // Create query items from passed-in options + id apnsTokenData = self.options[kFIRInstanceIDTokenOptionsAPNSKey]; + id apnsSandboxValue = self.options[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if ([apnsTokenData isKindOfClass:[NSData class]] && + [apnsSandboxValue isKindOfClass:[NSNumber class]]) { + NSString *APNSString = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + apnsTokenData, ((NSNumber *)apnsSandboxValue).boolValue); + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsAPNSKey + value:APNSString]; + [queryItems addObject:item]; + } + id firebaseAppID = self.options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + if ([firebaseAppID isKindOfClass:[NSString class]]) { + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsFirebaseAppIDKey + value:(NSString *)firebaseAppID]; + [queryItems addObject:item]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest, + @"Register request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +#pragma mark - Request Handling + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationRequestError, + @"Token fetch HTTP error. Error Code: %ld", (long)error.code); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSDictionary *parsedResponse = [self parseFetchTokenResponse:dataResponse]; + _FIRInstanceIDDevAssert(parsedResponse.count, @"Invalid registration response"); + + if ([parsedResponse[@"token"] length]) { + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded + token:parsedResponse[@"token"] + error:nil]; + return; + } + + NSString *errorValue = parsedResponse[@"Error"]; + NSError *responseError; + if (errorValue.length) { + NSArray *errorComponents = [errorValue componentsSeparatedByString:@":"]; + // HACK (Kansas replication delay), PHONE_REGISTRATION_ERROR on App + // uninstall and reinstall. + if ([errorComponents containsObject:@"PHONE_REGISTRATION_ERROR"]) { + // Encountered issue http://b/27043795 + // Retry register until successful or another error encountered or a + // certain number of tries are over. + + if (phoneRegistrationErrorRetryCount < kMaxPhoneRegistrationErrorRetryCount) { + const int nextRetryInterval = 1 << phoneRegistrationErrorRetryCount; + FIRInstanceID_WEAKIFY(self); + + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(nextRetryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + phoneRegistrationErrorRetryCount++; + [self performTokenOperation]; + }); + return; + } + } else if ([errorComponents containsObject:kFIRInstanceID_CMD_RST]) { + // Server detected the identity we use is no longer valid. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:kFIRInstanceIDIdentityInvalidatedNotification object:nil]; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal001, + @"Identity is invalid. Server request identity reset."); + responseError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidIdentity]; + } + } + if (!responseError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse, + @"Invalid fetch response, expected 'token' or 'Error' key"); + responseError = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:responseError]; +} + +// expect a response e.g. "token=\nGOOG.ttl=123" +- (NSDictionary *)parseFetchTokenResponse:(NSString *)response { + NSArray *lines = [response componentsSeparatedByString:@"\n"]; + NSMutableDictionary *parsedResponse = [NSMutableDictionary dictionary]; + for (NSString *line in lines) { + NSArray *keyAndValue = [line componentsSeparatedByString:@"="]; + if ([keyAndValue count] > 1) { + parsedResponse[keyAndValue[0]] = keyAndValue[1]; + } + } + return parsedResponse; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h new file mode 100644 index 0000000..34ad716 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h @@ -0,0 +1,82 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstanceIDAPNSInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an Instance ID token, and all of the relevant information + * associated with it. It can read from and write to an NSDictionary object, for + * simple serialization. + */ +@interface FIRInstanceIDTokenInfo : NSObject + +/// The authorized entity (also known as Sender ID), associated with the token. +@property(nonatomic, readonly, copy) NSString *authorizedEntity; +/// The scope associated with the token. This is an arbitrary string, typically "*". +@property(nonatomic, readonly, copy) NSString *scope; +/// The token value itself, with which all other properties are associated. +@property(nonatomic, readonly, copy) NSString *token; + +// These properties are nullable because they might not exist for tokens fetched from +// legacy storage formats. + +/// The app version that this token represents. +@property(nonatomic, readonly, copy, nullable) NSString *appVersion; +/// The Firebase app ID (also known as GMP App ID), that this token is associated with. +@property(nonatomic, readonly, copy, nullable) NSString *firebaseAppID; + +/// Tokens may not always be associated with an APNs token, and may be associated after +/// being created. +@property(nonatomic, strong, nullable) FIRInstanceIDAPNSInfo *APNSInfo; +/// The time that this token info was updated. The cache time is writeable, since in +/// some cases the token info may be refreshed from the server. In those situations, +/// the cacheTime would be updated. +@property(nonatomic, copy, nullable) NSDate *cacheTime; + +/** + * Initializes a FIRInstanceIDTokenInfo object with the required parameters. These + * parameters represent all the relevant associated data with a token. + * + * @param authorizedEntity The authorized entity (also known as Sender ID). + * @param scope The scope of the token, typically "*" meaning + * it's a "default scope". + * @param token The token value itself. + * @param appVersion The application version that this token is associated with. + * @param firebaseAppID The Firebase app ID which this token is associated with. + * @return An instance of FIRInstanceIDTokenInfo. + */ +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(nullable NSString *)appVersion + firebaseAppID:(nullable NSString *)firebaseAppID; + +/** + * Check whether the token is still fresh based on: + * 1. Last fetch token is within the 7 days. + * 2. Language setting is not changed. + * 3. App version is current. + * 4. GMP App ID is current. + */ +- (BOOL)isFresh; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m new file mode 100644 index 0000000..a4d284b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m @@ -0,0 +1,188 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenInfo.h" + +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" + +/** + * @enum Token Info Dictionary Key Constants + * @discussion The keys that are checked when a token info is + * created from a dictionary. The same keys are used + * when decoding/encoding an archive. + */ +/// Specifies a dictonary key whose value represents the authorized entity, or +/// Sender ID for the token. +static NSString *const kFIRInstanceIDAuthorizedEntityKey = @"authorized_entity"; +/// Specifies a dictionary key whose value represents the scope of the token, +/// typically "*". +static NSString *const kFIRInstanceIDScopeKey = @"scope"; +/// Specifies a dictionary key which represents the token value itself. +static NSString *const kFIRInstanceIDTokenKey = @"token"; +/// Specifies a dictionary key which represents the app version associated +/// with the token. +static NSString *const kFIRInstanceIDAppVersionKey = @"app_version"; +/// Specifies a dictionary key which represents the GMP App ID associated with +/// the token. +static NSString *const kFIRInstanceIDFirebaseAppIDKey = @"firebase_app_id"; +/// Specifies a dictionary key representing an archive for a +/// `FIRInstanceIDAPNSInfo` object. +static NSString *const kFIRInstanceIDAPNSInfoKey = @"apns_info"; +/// Specifies a dictionary key representing the "last cached" time for the token. +static NSString *const kFIRInstanceIDCacheTimeKey = @"cache_time"; +/// Default interval that token stays fresh. +const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60; // 7 days. + +@implementation FIRInstanceIDTokenInfo + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(NSString *)appVersion + firebaseAppID:(NSString *)firebaseAppID { + self = [super init]; + if (self) { + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _token = [token copy]; + _appVersion = [appVersion copy]; + _firebaseAppID = [firebaseAppID copy]; + } + return self; +} + +- (BOOL)isFresh { + // Last fetch token cache time could be null if token is from legacy storage format. Then token is + // considered not fresh and should be refreshed and overwrite with the latest storage format. + if (!_cacheTime) { + return NO; + } + + // Check if app has just been updated to a new version. + NSString *currentAppVersion = FIRInstanceIDCurrentAppVersion(); + if (!_appVersion || ![_appVersion isEqualToString:currentAppVersion]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager004, + @"Invalidating cached token for %@ (%@) due to app version change.", + _authorizedEntity, _scope); + return NO; + } + + // Check if GMP App ID has changed + NSString *currentFirebaseAppID = FIRInstanceIDFirebaseAppID(); + if (!_firebaseAppID || ![_firebaseAppID isEqualToString:currentFirebaseAppID]) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged, + @"Invalidating cached token due to Firebase App IID change from %@ to %@", _firebaseAppID, + currentFirebaseAppID); + return NO; + } + + // Check whether locale has changed, if yes, token needs to be updated with server for locale + // information. + if (FIRInstanceIDHasLocaleChanged()) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenInfoLocaleChanged, + @"Invalidating cached token due to locale change"); + return NO; + } + + // Locale is not changed, check whether token has been fetched within 7 days. + NSTimeInterval lastFetchTokenTimestamp = [_cacheTime timeIntervalSince1970]; + NSTimeInterval currentTimestamp = FIRInstanceIDCurrentTimestampInSeconds(); + NSTimeInterval timeSinceLastFetchToken = currentTimestamp - lastFetchTokenTimestamp; + return (timeSinceLastFetchToken < kDefaultFetchTokenInterval); +} +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + // These value cannot be nil + + id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey]; + if (![authorizedEntity isKindOfClass:[NSString class]]) { + return nil; + } + + id scope = [aDecoder decodeObjectForKey:kFIRInstanceIDScopeKey]; + if (![scope isKindOfClass:[NSString class]]) { + return nil; + } + + id token = [aDecoder decodeObjectForKey:kFIRInstanceIDTokenKey]; + if (![token isKindOfClass:[NSString class]]) { + return nil; + } + + // These values are nullable, so only fail the decode if the type does not match + + id appVersion = [aDecoder decodeObjectForKey:kFIRInstanceIDAppVersionKey]; + if (appVersion && ![appVersion isKindOfClass:[NSString class]]) { + return nil; + } + + id firebaseAppID = [aDecoder decodeObjectForKey:kFIRInstanceIDFirebaseAppIDKey]; + if (firebaseAppID && ![firebaseAppID isKindOfClass:[NSString class]]) { + return nil; + } + + id rawAPNSInfo = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoKey]; + if (rawAPNSInfo && ![rawAPNSInfo isKindOfClass:[NSData class]]) { + return nil; + } + + FIRInstanceIDAPNSInfo *APNSInfo = nil; + if (rawAPNSInfo) { + @try { + APNSInfo = [NSKeyedUnarchiver unarchiveObjectWithData:rawAPNSInfo]; + } @catch (NSException *exception) { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo, + @"Could not parse raw APNS Info while parsing archived token info."); + APNSInfo = nil; + } @finally { + } + } + + id cacheTime = [aDecoder decodeObjectForKey:kFIRInstanceIDCacheTimeKey]; + if (cacheTime && ![cacheTime isKindOfClass:[NSDate class]]) { + return nil; + } + + self = [super init]; + if (self) { + _authorizedEntity = authorizedEntity; + _scope = scope; + _token = token; + _appVersion = appVersion; + _firebaseAppID = firebaseAppID; + _APNSInfo = APNSInfo; + _cacheTime = cacheTime; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.authorizedEntity forKey:kFIRInstanceIDAuthorizedEntityKey]; + [aCoder encodeObject:self.scope forKey:kFIRInstanceIDScopeKey]; + [aCoder encodeObject:self.token forKey:kFIRInstanceIDTokenKey]; + [aCoder encodeObject:self.appVersion forKey:kFIRInstanceIDAppVersionKey]; + [aCoder encodeObject:self.firebaseAppID forKey:kFIRInstanceIDFirebaseAppIDKey]; + if (self.APNSInfo) { + NSData *rawAPNSInfo = [NSKeyedArchiver archivedDataWithRootObject:self.APNSInfo]; + [aCoder encodeObject:rawAPNSInfo forKey:kFIRInstanceIDAPNSInfoKey]; + } + [aCoder encodeObject:self.cacheTime forKey:kFIRInstanceIDCacheTimeKey]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h new file mode 100644 index 0000000..491b99c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +@class FIRInstanceIDAuthService; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDKeyPair; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDStore; + +typedef NS_OPTIONS(NSUInteger, FIRInstanceIDInvalidTokenReason) { + FIRInstanceIDInvalidTokenReasonNone = 0, // 0 + FIRInstanceIDInvalidTokenReasonAppVersion = (1 << 0), // 0...00001 + FIRInstanceIDInvalidTokenReasonAPNSToken = (1 << 1), // 0...00010 +}; + +/** + * Manager for the InstanceID token requests i.e `newToken` and `deleteToken`. This + * manages the overall interaction of the `InstanceIDStore`, the token register + * service and the callbacks associated with `GCMInstanceID`. + */ +@interface FIRInstanceIDTokenManager : NSObject + +/// Expose the auth service, so it can be used by others +@property(nonatomic, readonly, strong) FIRInstanceIDAuthService *authService; + +/** + * Fetch new token for the given authorizedEntity and scope. This makes an + * asynchronous request to the InstanceID backend to create a new token for + * the service and returns it. This will replace any old token for the given + * authorizedEntity and scope that has been cached before. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param keyPair The keyPair that represents the app identity. + * @param options The options to be added to the fetch request. + * @param handler The handler to be invoked once we have the token or the + * fetch request to InstanceID backend results in an error. Also + * since it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Return the cached token info, if one exists, for the given authorizedEntity and scope. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info, if available, matching the parameters. + */ +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Delete the token for the given authorizedEntity and scope. If the token has + * been cached, it will be deleted from the store. It will also make an + * asynchronous request to the InstanceID backend to invalidate the token. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param keyPair The keyPair that represents the app identity. + * @param handler The handler to be invoked once the delete request to + * InstanceID backend has returned. If the request was + * successful we invoke the handler with a nil error; + * otherwise we call it with an appropriate error. Also since + * it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. This method should only be triggered + * when InstanceID is deleted + * + * @param keyPair The keyPair for the given app. + * @param handler The handler to be invoked once the delete request to InstanceID backend + * has returned. If the request was successful we invoke the handler with + * a nil error; else we pass in an appropriate error. This should be non-nil + * and be called asynchronously. + */ +- (void)deleteAllTokensWithKeyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler; + +/** + * Stop any ongoing token operations. + */ +- (void)stopAllTokenOperations; + +#pragma mark - Invalidating Cached Tokens + +/** + * Invalidate any cached tokens, if the app version has changed since last launch or if the token + * is cached for more than 7 days. + * + * @return Whether we should fetch default token from server. + * + * @discussion This should safely be called prior to any tokens being retrieved from + * the cache or being fetched from the network. + */ +- (BOOL)checkForTokenRefreshPolicy; + +/** + * Upon being provided with different APNs or sandbox, any locally cached tokens + * should be deleted, and the new APNs token should be cached. + * + * @discussion It is possible for this method to be called while token operations are + * in-progress or queued. In this case, the in-flight token operations will have stale + * APNs information. The default token is checked for being out-of-date by Instance ID, + * and re-fetched. Custom tokens are not currently checked. + * + * @param deviceToken The APNS device token, provided by the operating system. + * @param isSandbox YES if the device token is for the sandbox environment, NO otherwise. + * + * @return The array of FIRInstanceIDTokenInfo objects which were invalidated. + */ +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m new file mode 100644 index 0000000..0c4f644 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m @@ -0,0 +1,341 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenManager.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenDeleteOperation.h" +#import "FIRInstanceIDTokenFetchOperation.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenOperation.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDTokenManager () + +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *instanceIDStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthService *authService; +@property(nonatomic, readonly, strong) NSOperationQueue *tokenOperations; + +@property(nonatomic, readwrite, strong) FIRInstanceIDAPNSInfo *currentAPNSInfo; + +@end + +@implementation FIRInstanceIDTokenManager + +- (instancetype)init { + self = [super init]; + if (self) { + _instanceIDStore = [[FIRInstanceIDStore alloc] initWithDelegate:self]; + _authService = [[FIRInstanceIDAuthService alloc] initWithStore:_instanceIDStore]; + [self configureTokenOperations]; + } + return self; +} + +- (void)dealloc { + [self stopAllTokenOperations]; +} + +- (void)configureTokenOperations { + _tokenOperations = [[NSOperationQueue alloc] init]; + _tokenOperations.name = @"com.google.iid-token-operations"; + // For now, restrict the operations to be serial, because in some cases (like if the + // authorized entity and scope are the same), order matters. + // If we have to deal with several different token requests simultaneously, it would be a good + // idea to add some better intelligence around this (performing unrelated token operations + // simultaneously, etc.). + _tokenOperations.maxConcurrentOperationCount = 1; + if ([_tokenOperations respondsToSelector:@selector(qualityOfService)]) { + _tokenOperations.qualityOfService = NSOperationQualityOfServiceUtility; + } +} + +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager000, + @"Fetch new token for authorizedEntity: %@, scope: %@", authorizedEntity, + scope); + FIRInstanceIDTokenFetchOperation *operation = + [self createFetchOperationWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + keyPair:keyPair]; + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenOperationCompletion completion = + ^(FIRInstanceIDTokenOperationResult result, NSString *_Nullable token, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + handler(nil, error); + return; + } + NSString *firebaseAppID = options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + FIRInstanceIDTokenInfo *tokenInfo = [[FIRInstanceIDTokenInfo alloc] + initWithAuthorizedEntity:authorizedEntity + scope:scope + token:token + appVersion:FIRInstanceIDCurrentAppVersion() + firebaseAppID:firebaseAppID]; + tokenInfo.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:options]; + + [self.instanceIDStore + saveTokenInfo:tokenInfo + handler:^(NSError *error) { + if (!error) { + // Do not send the token back in case the save was unsuccessful. Since with + // the new asychronous fetch mechanism this can lead to infinite loops, for + // example, we will return a valid token even though we weren't able to store + // it in our cache. The first token will lead to a onTokenRefresh callback + // wherein the user again calls `getToken` but since we weren't able to save + // it we won't hit the cache but hit the server again leading to an infinite + // loop. + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManager001, + @"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@", + token, authorizedEntity, scope); + + if (handler) { + handler(token, nil); + } + } else { + if (handler) { + handler(nil, error); + } + } + }]; + }; + // Add completion handler, and ensure it's called on the main queue + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(result, token, error); + }); + }]; + [self.tokenOperations addOperation:operation]; +} + +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + return [self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if ([self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:authorizedEntity scope:scope]; + } + // Does not matter if we cannot find it in the cache. Still make an effort to unregister + // from the server. + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + keyPair:keyPair + action:FIRInstanceIDTokenActionDeleteToken]; + + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensWithKeyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteHandler)handler { + // delete all tokens + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + if (!checkinPreferences) { + // The checkin is already deleted. No need to trigger the token delete operation as client no + // longer has the checkin information for server to delete. + dispatch_async(dispatch_get_main_queue(), ^{ + handler(nil); + }); + return; + } + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:kFIRInstanceIDKeychainWildcardIdentifier + scope:kFIRInstanceIDKeychainWildcardIdentifier + checkinPreferences:checkinPreferences + keyPair:keyPair + action:FIRInstanceIDTokenActionDeleteTokenAndIID]; + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler { + [self.instanceIDStore removeAllCachedTokensWithHandler:handler]; +} + +- (void)stopAllTokenOperations { + [self.authService stopCheckinRequest]; + [self.tokenOperations cancelAllOperations]; +} + +#pragma mark - FIRInstanceIDStoreDelegate + +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + // Make a best effort try to delete the old client related state on the FCM server. This is + // required to delete old pubusb registrations which weren't cleared when the app was deleted. + // + // This is only a one time effort. If this call fails the client would still receive duplicate + // pubsub notifications if he is again subscribed to the same topic. + // + // The client state should be cleared on the server for the provided checkin preferences. + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:nil + scope:nil + checkinPreferences:checkin + keyPair:nil + action:FIRInstanceIDTokenActionDeleteToken]; + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + FIRInstanceIDMessageCode code = + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset; + FIRInstanceIDLoggerDebug(code, @"Failed to delete GCM server registrations on app reset."); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset, + @"Successfully deleted GCM server registrations on app reset"); + } + }]; + + [self.tokenOperations addOperation:operation]; +} + +#pragma mark - Unit Testing Stub Helpers +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenFetchOperation *) + createFetchOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + keyPair:(FIRInstanceIDKeyPair *)keyPair { + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenFetchOperation *operation = + [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + keyPair:keyPair]; + return operation; +} + +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenDeleteOperation *) + createDeleteOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair + action:(FIRInstanceIDTokenAction)action { + FIRInstanceIDTokenDeleteOperation *operation = + [[FIRInstanceIDTokenDeleteOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + keyPair:keyPair + action:action]; + return operation; +} + +#pragma mark - Invalidating Cached Tokens +- (BOOL)checkForTokenRefreshPolicy { + // We know at least one cached token exists. + BOOL shouldFetchDefaultToken = NO; + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *tokenInfo in tokenInfos) { + BOOL isTokenFresh = [tokenInfo isFresh]; + if (isTokenFresh) { + // Token is fresh, do nothing. + continue; + } + if ([tokenInfo.scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + // Default token is expired, do not mark for deletion. Fetch directly from server to + // replace the current one. + shouldFetchDefaultToken = YES; + } else { + // Non-default token is expired, mark for deletion. + [tokenInfosToDelete addObject:tokenInfo]; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken, + @"Invalidating cached token for %@ (%@) due to token is no longer fresh.", + tokenInfo.authorizedEntity, tokenInfo.scope); + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return shouldFetchDefaultToken; +} + +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox { + // Each cached IID token that is missing an APNSInfo, or has an APNSInfo associated should be + // checked and invalidated if needed. + FIRInstanceIDAPNSInfo *APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:deviceToken + isSandbox:isSandbox]; + if ([self.currentAPNSInfo isEqualToAPNSInfo:APNSInfo]) { + return @[]; + } + self.currentAPNSInfo = APNSInfo; + + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *cachedTokenInfo in tokenInfos) { + // Check if the cached APNSInfo is nil, or if it is an old APNSInfo. + if (!cachedTokenInfo.APNSInfo || + ![cachedTokenInfo.APNSInfo isEqualToAPNSInfo:self.currentAPNSInfo]) { + // Mark for invalidation. + [tokenInfosToDelete addObject:cachedTokenInfo]; + } + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated, + @"Invalidating cached token for %@ (%@) due to APNs token change.", + tokenInfoToDelete.authorizedEntity, tokenInfoToDelete.scope); + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return tokenInfosToDelete; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h new file mode 100644 index 0000000..68d9db1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h @@ -0,0 +1,67 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDUtilities.h" + +@class FIRInstanceIDKeyPair; +@class FIRInstanceIDURLQueryItem; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenOperation (Private) + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + ++ (NSURLSession *)sharedURLSession; + +#pragma mark - Initialization +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair; + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString; ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope; +- (NSArray *)queryItemsWithKeyPair:(FIRInstanceIDKeyPair *)keyPair; + +#pragma mark - HTTP Headers +/** + * Given a valid checkin preferences object, it will return a string that can be used + * in the "Authorization" HTTP header to authenticate this request. + * + * @param checkin The valid checkin preferences object, with a deviceID and secretToken. + */ ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +#pragma mark - Result +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h new file mode 100644 index 0000000..1a1842c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDKeyPair; +@class FIRInstanceIDCheckinPreferences; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on an FCM token. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenAction) { + FIRInstanceIDTokenActionFetch, + FIRInstanceIDTokenActionDeleteToken, + FIRInstanceIDTokenActionDeleteTokenAndIID, +}; + +/** + * Represents the possible results of a token operation. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenOperationResult) { + FIRInstanceIDTokenOperationSucceeded, + FIRInstanceIDTokenOperationError, + FIRInstanceIDTokenOperationCancelled, +}; + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param result The result of the operation. + * @param token If the action for fetching a token and the request was successful, this will hold + * the value of the token. Otherwise nil. + * @param error The error which occurred while performing the token operation. This will be nil + * in case the operation was successful, or if the operation was cancelled. + */ +typedef void (^FIRInstanceIDTokenOperationCompletion)(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, + NSError *_Nullable error); + +@interface FIRInstanceIDTokenOperation : NSOperation + +@property(nonatomic, readonly) FIRInstanceIDTokenAction action; +@property(nonatomic, readonly, nullable) NSString *authorizedEntity; +@property(nonatomic, readonly, nullable) NSString *scope; +@property(nonatomic, readonly, nullable) NSDictionary *options; +@property(nonatomic, readonly, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readonly, strong) FIRInstanceIDKeyPair *keyPair; + +@property(nonatomic, readonly) FIRInstanceIDTokenOperationResult result; + +- (instancetype)init NS_UNAVAILABLE; + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m new file mode 100644 index 0000000..dcfdb84 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m @@ -0,0 +1,243 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2; + +static NSString *const kFIRInstanceIDParamInstanceID = @"appid"; +// Scope parameter that defines the service using the token +static NSString *const kFIRInstanceIDParamScope = @"X-scope"; +// Defines the SDK version +static NSString *const kFIRInstanceIDParamFCMLibVersion = @"X-cliv"; + +@interface FIRInstanceIDTokenOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + +@end + +@implementation FIRInstanceIDTokenOperation + ++ (NSURLSession *)sharedURLSession { + static NSURLSession *tokenOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + tokenOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + tokenOperationSharedSession.sessionDescription = @"com.google.iid.tokens.session"; + }); + return tokenOperationSharedSession; +} + +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair { + self = [super init]; + if (self) { + _action = action; + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _options = [options copy]; + _checkinPreferences = checkinPreferences; + _keyPair = keyPair; + _completionHandlers = [NSMutableArray array]; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _testBlock = nil; + _authorizedEntity = nil; + _scope = nil; + _options = nil; + _checkinPreferences = nil; + _keyPair = nil; + [_completionHandlers removeAllObjects]; + _completionHandlers = nil; +} + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler { + [self.completionHandlers addObject:handler]; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; + return; + } + + // Quickly validate whether or not the operation has all it needs to begin + BOOL checkinfoAvailable = [self.checkinPreferences hasCheckinInfo]; + _FIRInstanceIDDevAssert(checkinfoAvailable, @"Cannot fetch token invalid checkin state"); + if (!checkinfoAvailable) { + FIRInstanceIDErrorCode errorCode = kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn; + [self finishWithResult:FIRInstanceIDTokenOperationError + token:nil + error:[NSError errorWithFIRInstanceIDErrorCode:errorCode]]; + return; + } + + [self setExecuting:YES]; + + [self performTokenOperation]; +} + +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + _result = result; + // TODO(chliangGoogle): Call these in the main thread? + for (FIRInstanceIDTokenOperationCompletion completionHandler in self.completionHandlers) { + completionHandler(result, token, error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; +} + +- (void)performTokenOperation { +} + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString { + NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + // Add HTTP headers + [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"]; + [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"]; + request.HTTPMethod = @"POST"; + return request; +} + ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope { + NSMutableArray *queryItems = [NSMutableArray arrayWithCapacity:8]; + + // E.g. X-osv=10.2.1 + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]]; + // E.g. device= + if (deviceID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"device" value:deviceID]]; + } + // E.g. X-scope=fcm + if (scope) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamScope + value:scope]]; + } + // E.g. plat=2 + NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"plat" value:platform]]; + // E.g. app=com.myapp.foo + NSString *appIdentifier = FIRInstanceIDAppIdentifier(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app" value:appIdentifier]]; + // E.g. app_ver=1.5 + NSString *appVersion = FIRInstanceIDCurrentAppVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app_ver" value:appVersion]]; + // E.g. X-cliv=fiid-1.2.3 + NSString *fcmLibraryVersion = + [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()]; + if (fcmLibraryVersion.length) { + FIRInstanceIDURLQueryItem *gcmLibVersion = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion + value:fcmLibraryVersion]; + [queryItems addObject:gcmLibVersion]; + } + + return queryItems; +} + +- (NSArray *)queryItemsWithKeyPair:(FIRInstanceIDKeyPair *)keyPair { + NSMutableArray *items = [NSMutableArray arrayWithCapacity:3]; + // appid= + NSString *instanceID = FIRInstanceIDAppIdentity(keyPair); + [items addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID + value:instanceID]]; + return items; +} + +#pragma mark - HTTP Header + ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + NSString *deviceID = checkin.deviceID; + NSString *secret = checkin.secretToken; + return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret]; +} +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h new file mode 100644 index 0000000..861c87b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAPNSInfo; +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDTokenInfo; + +/** + * This class is responsible for retrieving and saving `FIRInstanceIDTokenInfo` objects from the + * keychain. The keychain keys that are used are: + * Account:
(e.g. com.mycompany.myapp) + * Service: : (e.g. 1234567890:*) + */ +@interface FIRInstanceIDTokenStore : NSObject + +NS_ASSUME_NONNULL_BEGIN + +/** + * Create a default InstanceID token store. Uses a valid Keychain object as it's + * persistent backing store. + * + * @return A valid token store object. + */ ++ (instancetype)defaultStore; + +- (instancetype)init __attribute__((unavailable("Use -initWithKeychain: instead."))); + +/** + * Initialize a token store object with a Keychain object. Used for testing. + * + * @param keychain The Keychain object to use as the backing store for tokens. + * + * @return A valid token store object with the given Keychain as backing store. + */ +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain; + +#pragma mark - Get + +/** + * Get the cached token from the Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Save + +/** + * Save the instanceID token info to the persistent store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when token saving is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(nullable void (^)(NSError *))handler; + +#pragma mark - Delete + +/** + * Remove the cached token from Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + */ +- (void)removeTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Remove all the cached tokens from the Keychain. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)removeAllTokensWithHandler:(nullable void (^)(NSError *))handler; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m new file mode 100644 index 0000000..baadc89 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m @@ -0,0 +1,137 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kFIRInstanceIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstanceIDTokenStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; + +@end + +@implementation FIRInstanceIDTokenStore + ++ (instancetype)defaultStore { + FIRInstanceIDAuthKeychain *tokenKeychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDTokenKeychainId]; + return [[FIRInstanceIDTokenStore alloc] initWithKeychain:tokenKeychain]; +} + +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _keychain = keychain; + } + return self; +} + +#pragma mark - Get + ++ (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + NSData *item = [self.keychain dataForService:service account:account]; + if (!item) { + return nil; + } + // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo. + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + return tokenInfo; +} + +- (NSArray *)cachedTokenInfos { + NSString *account = FIRInstanceIDAppIdentifier(); + NSArray *items = + [self.keychain itemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier account:account]; + NSMutableArray *tokenInfos = + [NSMutableArray arrayWithCapacity:items.count]; + for (NSData *item in items) { + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + if (tokenInfo) { + [tokenInfos addObject:tokenInfo]; + } + } + return tokenInfos; +} + ++ (nullable FIRInstanceIDTokenInfo *)tokenInfoFromKeychainItem:(NSData *)item { + // Check if it is saved as an archived FIRInstanceIDTokenInfo, otherwise return nil. + FIRInstanceIDTokenInfo *tokenInfo = nil; + // NOTE: Passing in nil to unarchiveObjectWithData will result in an iOS error logged + // in the console on iOS 10 and below. Avoid by checking item.data's existence. + if (item) { + @try { + tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item]; + } @catch (NSException *exception) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo, + @"Unable to parse token info from Keychain item; item was in an " + @"invalid format"); + tokenInfo = nil; + } @finally { + } + } + return tokenInfo; +} + +#pragma mark - Save +// Token Infos will be saved under these Keychain keys: +// Account:
(e.g. com.mycompany.myapp) +// Service: : (e.g. 1234567890:*) +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *))handler { // Keep the cachetime up-to-date. + tokenInfo.cacheTime = [NSDate date]; + // Always write to the Keychain, so that the cacheTime is up-to-date. + NSData *tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo]; + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope]; + [self.keychain setData:tokenInfoData + forService:service + accessibility:NULL + account:account + handler:handler]; +} + +#pragma mark - Delete + +- (void)removeTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity + scope:(nonnull NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + [self.keychain removeItemsMatchingService:service account:account handler:nil]; +} + +- (void)removeAllTokensWithHandler:(void (^)(NSError *error))handler { + NSString *account = FIRInstanceIDAppIdentifier(); + [self.keychain removeItemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier + account:account + handler:handler]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h new file mode 100644 index 0000000..3a3a1d7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// Stand-in for NSURLQueryItem, which is only available on iOS 8.0 and up. +@interface FIRInstanceIDURLQueryItem : NSObject + +@property(nonatomic, readonly) NSString *name; +@property(nonatomic, readonly) NSString *value; + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value; +- (instancetype)initWithName:(NSString *)name value:(NSString *)value; + +@end + +/** + * Given an array of query items, construct a URL query. On iOS 8.0 and above, this will use + * NSURLQueryItems internally to perform the string creation, and will be done manually in iOS + * 7 and below. + */ +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems); + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m new file mode 100644 index 0000000..59b4865 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDURLQueryItem.h" + +@implementation FIRInstanceIDURLQueryItem + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value { + return [[[self class] alloc] initWithName:name value:value]; +} + +- (instancetype)initWithName:(NSString *)name value:(NSString *)value { + self = [super init]; + if (self) { + _name = [name copy]; + _value = [value copy]; + } + return self; +} +@end + +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems) { + if ([NSURLQueryItem class]) { + // We are iOS 8.0 and above. Convert to NSURLQueryItems and get query that way + // to take advantage of any automatic encoding + NSMutableArray *urlItems = + [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [urlItems addObject:[NSURLQueryItem queryItemWithName:queryItem.name value:queryItem.value]]; + } + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = urlItems; + return components.query; + } else { + // We are on iOS 7.0. Manually create the query string + NSMutableArray *pairs = [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [pairs addObject:[NSString stringWithFormat:@"%@=%@", queryItem.name, queryItem.value]]; + } + return [pairs componentsJoinedByString:@"&"]; + } +} diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h new file mode 100644 index 0000000..da6ebad --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFCMSDKClassString; + +/// locale key stored in GULUserDefaults +FOUNDATION_EXPORT NSString *const kFIRInstanceIDUserDefaultsKeyLocale; + +#pragma mark - Test Blocks + +/** + * Response block for mock registration requests made during tests. + * + * @param data The data as returned by the mock request. + * @param response The response as returned by the mock request. + * @param error The error if any as returned by the mock request. + */ +typedef void (^FIRInstanceIDURLRequestTestResponseBlock)(NSData *data, + NSURLResponse *response, + NSError *error); + +/** + * Test block to mock registration requests response. + * + * @param request The request to mock response for. + * @param response The response block for the mocked request. + */ +typedef void (^FIRInstanceIDURLRequestTestBlock)(NSURLRequest *request, + FIRInstanceIDURLRequestTestResponseBlock response); + +#pragma mark - URL Helpers + +FOUNDATION_EXPORT NSString *FIRInstanceIDRegisterServer(void); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentifier(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDFirebaseAppID(void); + +#pragma mark - Device Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDDeviceModel(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDOperatingSystemVersion(void); +FOUNDATION_EXPORT BOOL FIRInstanceIDHasLocaleChanged(void); + +#pragma mark - Helpers + +FOUNDATION_EXPORT BOOL FIRInstanceIDIsValidGCMScope(NSString *scope); +FOUNDATION_EXPORT NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken); +FOUNDATION_EXPORT NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, + BOOL isSandbox); + +#pragma mark - GCM Helpers +/// Returns the current GCM version if GCM library is found else returns nil. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentGCMVersion(void); + +/// Returns the current locale. If GCM is present it queries GCM for a +/// Context Manager specific locale. Otherwise, it returns the system's first +/// preferred language (which may be set independently from locale). If the +/// system returns no preferred languages, this method returns the most common +/// language for the user's given locale. Guaranteed to return a nonnull value. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLocale(void); diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m new file mode 100644 index 0000000..6b7ca96 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m @@ -0,0 +1,194 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDUtilities.h" + +#import +#import + +#import +#import +#import "FIRInstanceID.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kFIRInstanceIDAPNSSandboxPrefix = @"s_"; +static NSString *const kFIRInstanceIDAPNSProdPrefix = @"p_"; + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +NSString *const kFIRInstanceIDFCMSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRInstanceIDFCMSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRInstanceIDFCMSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; + +NSString *const kFIRInstanceIDUserDefaultsKeyLocale = + @"com.firebase.instanceid.user_defaults.locale"; // locale key stored in GULUserDefaults + +/// Static values which will be populated once retrieved using +/// |FIRInstanceIDRetrieveEnvironmentInfoFromFirebaseCore|. +static NSString *operatingSystemVersion; +static NSString *hardwareDeviceModel; + +#pragma mark - URL Helpers + +NSString *FIRInstanceIDRegisterServer() { + return @"https://fcmtoken.googleapis.com/register"; +} + +#pragma mark - Time + +int64_t FIRInstanceIDCurrentTimestampInSeconds() { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRInstanceIDCurrentTimestampInMilliseconds() { + return (int64_t)(FIRInstanceIDCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRInstanceIDCurrentAppVersion() { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + return @""; + } + return version; +} + +NSString *FIRInstanceIDAppIdentifier() { + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleIdentifier.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier, + @"The mainBundle's bundleIdentifier returned '%@'. Bundle identifier " + @"expected to be non-empty.", + bundleIdentifier); + return @""; + } + return bundleIdentifier; +} + +NSString *FIRInstanceIDFirebaseAppID() { + return [FIROptions defaultOptions].googleAppID; +} + +#pragma mark - Device Info +// Get the device model from Firebase Core's App Environment Util +NSString *FIRInstanceIDDeviceModel() { + static dispatch_once_t once; + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + hardwareDeviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return hardwareDeviceModel; +} + +// Get the system version from Firebase Core's App Environment Util +NSString *FIRInstanceIDOperatingSystemVersion() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX + return [NSProcessInfo processInfo].operatingSystemVersionString; +#endif +} + +BOOL FIRInstanceIDHasLocaleChanged() { + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + if (lastLocale) { + if ([currentLocale isEqualToString:lastLocale]) { + return NO; + } + } + return YES; +} + +#pragma mark - Helpers + +BOOL FIRInstanceIDIsValidGCMScope(NSString *scope) { + return [scope compare:kFIRInstanceIDScopeFirebaseMessaging + options:NSCaseInsensitiveSearch] == NSOrderedSame; +} + +NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken) { + NSMutableString *APNSToken = [NSMutableString string]; + unsigned char *bytes = (unsigned char *)[deviceToken bytes]; + for (int i = 0; i < (int)deviceToken.length; i++) { + [APNSToken appendFormat:@"%02x", bytes[i]]; + } + return APNSToken; +} + +NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, BOOL isSandbox) { + if (deviceToken == nil) { + // A nil deviceToken leads to an invalid tuple string, so return nil. + return nil; + } + NSString *prefix = isSandbox ? kFIRInstanceIDAPNSSandboxPrefix : kFIRInstanceIDAPNSProdPrefix; + NSString *APNSString = FIRInstanceIDStringForAPNSDeviceToken(deviceToken); + NSString *APNSTupleString = [NSString stringWithFormat:@"%@%@", prefix, APNSString]; + + return APNSTupleString; +} + +#pragma mark - GCM Helpers + +NSString *FIRInstanceIDCurrentGCMVersion() { + Class versionClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL versionSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKVersionSelectorString); + if ([versionClass respondsToSelector:versionSelector]) { + IMP getVersionIMP = [versionClass methodForSelector:versionSelector]; + NSString *(*getVersion)(id, SEL) = (void *)getVersionIMP; + return getVersion(versionClass, versionSelector); + } + return nil; +} + +NSString *FIRInstanceIDCurrentLocale() { + Class localeClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL localeSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKLocaleSelectorString); + + if ([localeClass respondsToSelector:localeSelector]) { + IMP getLocaleIMP = [localeClass methodForSelector:localeSelector]; + NSString *(*getLocale)(id, SEL) = (void *)getLocaleIMP; + NSString *fcmLocale = getLocale(localeClass, localeSelector); + if (fcmLocale != nil) { + return fcmLocale; + } + } + + NSString *systemLanguage = [[NSLocale preferredLanguages] firstObject]; + if (systemLanguage != nil) { + return systemLanguage; + } + + if (@available(iOS 10.0, *)) { + return [NSLocale currentLocale].languageCode; + } else { + return nil; + } +} diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h new file mode 100644 index 0000000..ec5a76c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Parsing utility for InstanceID Library versions. InstanceID lib follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLibraryVersion(void); +/// Returns the current Major version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRInstanceIDCurrentLibraryVersionIsBeta(void); diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m new file mode 100644 index 0000000..d6b0945 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDVersionUtilities.h" + +#import "FIRInstanceIDDefines.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; + +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRInstanceIDParseCurrentLibraryVersion() { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = + [NSMutableString stringWithUTF8String:STR(FIRInstanceID_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + _FIRInstanceIDDevAssert(allVersions.count == 3, @"Invalid versioning of FIRInstanceID library"); + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + _FIRInstanceIDDevAssert(patchAndBetaVersion.count <= 2, + @"Invalid versioning of FIRInstanceID library"); + + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRInstanceIDCurrentLibraryVersion() { + FIRInstanceIDParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMajor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMinor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionPatch() { + FIRInstanceIDParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRInstanceIDCurrentLibraryVersionIsBeta() { + FIRInstanceIDParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h new file mode 100644 index 0000000..b533dc4 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDomain; + +typedef NS_ENUM(NSUInteger, FIRInstanceIDErrorCode) { + // Unknown error. + kFIRInstanceIDErrorCodeUnknown = 0, + + // Http related errors. + kFIRInstanceIDErrorCodeAuthentication = 1, + kFIRInstanceIDErrorCodeNoAccess = 2, + kFIRInstanceIDErrorCodeTimeout = 3, + kFIRInstanceIDErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRInstanceIDErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRInstanceIDErrorCodeInvalidRequest = 7, + + // InstanceID generic errors + kFIRInstanceIDErrorCodeMissingDeviceID = 501, + + // InstanceID Token specific errors + kFIRInstanceIDErrorCodeMissingAPNSToken = 1001, + kFIRInstanceIDErrorCodeMissingAPNSServerType = 1002, + kFIRInstanceIDErrorCodeInvalidAuthorizedEntity = 1003, + kFIRInstanceIDErrorCodeInvalidScope = 1004, + kFIRInstanceIDErrorCodeInvalidStart = 1005, + kFIRInstanceIDErrorCodeInvalidKeyPair = 1006, + + // InstanceID Identity specific errors + // Generic InstanceID keypair error + kFIRInstanceIDErrorCodeMissingKeyPair = 2001, + kFIRInstanceIDErrorCodeInvalidKeyPairTags = 2002, + kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime = 2005, + kFIRInstanceIDErrorCodeInvalidIdentity = 2006, + +}; + +@interface NSError (FIRInstanceID) + +@property(nonatomic, readonly) FIRInstanceIDErrorCode instanceIDErrorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo; + ++ (NSError *)FIRInstanceIDErrorMissingCheckin; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m new file mode 100644 index 0000000..560a5df --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRInstanceID.h" + +NSString *const kFIRInstanceIDDomain = @"com.firebase.iid"; + +@implementation NSError (FIRInstanceID) + +- (FIRInstanceIDErrorCode)instanceIDErrorCode { + return (FIRInstanceIDErrorCode)self.code; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode { + return [NSError errorWithFIRInstanceIDErrorCode:errorCode userInfo:nil]; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRInstanceIDDomain code:errorCode userInfo:userInfo]; +} + ++ (NSError *)FIRInstanceIDErrorMissingCheckin { + NSDictionary *userInfo = @{@"msg" : @"Missing device credentials. Retry later."}; + + return [NSError errorWithDomain:kFIRInstanceIDDomain + code:kFIRInstanceIDErrorCodeMissingDeviceID + userInfo:userInfo]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h new file mode 100644 index 0000000..6a9e2d3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Private API used by other Firebase SDKs. + */ +@interface FIRInstanceID () + +/** + * Private initializer. + */ +- (nonnull instancetype)initPrivately; + +/** + * Returns a Firebase Messaging scoped token for the firebase app. + * + * @return Returns the stored token if the device has registered with Firebase Messaging, otherwise + * returns nil. + */ +- (nullable NSString *)token; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h new file mode 100644 index 0000000..c187d55 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h @@ -0,0 +1,312 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDResult; +/** + * @memberof FIRInstanceID + * + * The scope to be used when fetching/deleting a token for Firebase Messaging. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDScopeFirebaseMessaging + NS_SWIFT_NAME(InstanceIDScopeFirebaseMessaging); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT const NSNotificationName kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefresh); +#else +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefreshNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID token returns. If + * the call fails we return the appropriate `error code` as described below. + * + * @param token The valid token as returned by InstanceID backend. + * + * @param error The error describing why generating a new token + * failed. See the error codes below for a more detailed + * description. + */ +typedef void (^FIRInstanceIDTokenHandler)(NSString *__nullable token, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID `deleteToken` returns. If + * the call fails we return the appropriate `error code` as described below + * + * @param error The error describing why deleting the token failed. + * See the error codes below for a more detailed description. + */ +typedef void (^FIRInstanceIDDeleteTokenHandler)(NSError *error) + NS_SWIFT_NAME(InstanceIDDeleteTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity is created. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param identity A valid identity for the app instance, nil if there was an error + * while creating an identity. + * @param error The error if fetching the identity fails else nil. + */ +typedef void (^FIRInstanceIDHandler)(NSString *__nullable identity, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and all the tokens associated + * with it are deleted. Returns a valid error object in case of failure else nil. + * + * @param error The error if deleting the identity and all the tokens associated with + * it fails else nil. + */ +typedef void (^FIRInstanceIDDeleteHandler)(NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDDeleteHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and token are fetched. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param result The result containing an identity for the app instance and a valid token, + * nil if there was an error while creating the result. + * @param error The error if fetching the identity or token fails else nil. + */ +typedef void (^FIRInstanceIDResultHandler)(FIRInstanceIDResult *__nullable result, + NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDResultHandler); + +/** + * Public errors produced by InstanceID. + */ +typedef NS_ENUM(NSUInteger, FIRInstanceIDError) { + // Http related errors. + + /// Unknown error. + FIRInstanceIDErrorUnknown = 0, + + /// Auth Error -- GCM couldn't validate request from this client. + FIRInstanceIDErrorAuthentication = 1, + + /// NoAccess -- InstanceID service cannot be accessed. + FIRInstanceIDErrorNoAccess = 2, + + /// Timeout -- Request to InstanceID backend timed out. + FIRInstanceIDErrorTimeout = 3, + + /// Network -- No network available to reach the servers. + FIRInstanceIDErrorNetwork = 4, + + /// OperationInProgress -- Another similar operation in progress, + /// bailing this one. + FIRInstanceIDErrorOperationInProgress = 5, + + /// InvalidRequest -- Some parameters of the request were invalid. + FIRInstanceIDErrorInvalidRequest = 7, +} NS_SWIFT_NAME(InstanceIDError); + +/** + * A class contains the results of InstanceID and token query. + */ +NS_SWIFT_NAME(InstanceIDResult) +@interface FIRInstanceIDResult : NSObject + +/** + * An instanceID uniquely identifies the app instance. + */ +@property(nonatomic, readonly, copy) NSString *instanceID; + +/* + * Returns a Firebase Messaging scoped token for the firebase app. + */ +@property(nonatomic, readonly, copy) NSString *token; + +@end + +/** + * Instance ID provides a unique identifier for each app instance and a mechanism + * to authenticate and authorize actions (for example, sending an FCM message). + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * Instance ID is long lived but, may be reset if the device is not used for + * a long time or the Instance ID service detects a problem. + * If Instance ID is reset, the app will be notified via + * `kFIRInstanceIDTokenRefreshNotification`. + * + * If the Instance ID has become invalid, the app can request a new one and + * send it to the app server. + * To prove ownership of Instance ID and to allow servers to access data or + * services associated with the app, call + * `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + */ +NS_SWIFT_NAME(InstanceID) +@interface FIRInstanceID : NSObject + +/** + * FIRInstanceID. + * + * @return A shared instance of FIRInstanceID. + */ ++ (instancetype)instanceID NS_SWIFT_NAME(instanceID()); + +/** + * Unavailable. Use +instanceID instead. + */ +- (instancetype)init __attribute__((unavailable("Use +instanceID instead."))); + +#pragma mark - Tokens + +/** + * Returns a result of app instance identifier InstanceID and a Firebase Messaging scoped token. + * param handler The callback handler invoked when an app instanceID and a default token + * are generated and returned. If instanceID and token fetching fail for some + * reason the callback is invoked with nil `result` and the appropriate error. + */ +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler; + +/** + * Returns a token that authorizes an Entity (example: cloud service) to perform + * an action on behalf of the application identified by Instance ID. + * + * This is similar to an OAuth2 token except, it applies to the + * application instance instead of a user. + * + * This is an asynchronous call. If the token fetching fails for some reason + * we invoke the completion callback with nil `token` and the appropriate + * error. + * + * This generates an Instance ID if it does not exist yet, which starts periodically sending + * information to the Firebase backend (see `[FIRInstanceID getIDWithHandler:]`). + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at any point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an + * error with code `OperationInProgress`. + * + * @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler: + * + * @param authorizedEntity Entity authorized by the token. + * @param scope Action authorized for authorizedEntity. + * @param options The extra options to be sent with your token request. The + * value for the `apns_token` should be the NSData object + * passed to the UIApplicationDelegate's + * `didRegisterForRemoteNotificationsWithDeviceToken` method. + * The value for `apns_sandbox` should be a boolean (or an + * NSNumber representing a BOOL in Objective C) set to true if + * your app is a debug build, which means that the APNs + * device token is for the sandbox environment. It should be + * set to false otherwise. If the `apns_sandbox` key is not + * provided, an automatically-detected value shall be used. + * @param handler The callback handler which is invoked when the token is + * successfully fetched. In case of success a valid `token` and + * `nil` error are returned. In case of any error the `token` + * is nil and a valid `error` is returned. The valid error + * codes have been documented above. + */ +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Revokes access to a scope (action) for an entity previously + * authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + * + * This is an asynchronous call. Call this on the main thread since InstanceID lib + * is not thread safe. In case token deletion fails for some reason we invoke the + * `handler` callback passed in with the appropriate error code. + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at a point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an error + * with code `OperationInProgress`. + * + * @param authorizedEntity Entity that must no longer have access. + * @param scope Action that entity is no longer authorized to perform. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of error an appropriate error object is returned + * else error is nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +#pragma mark - Identity + +/** + * Asynchronously fetch a stable identifier that uniquely identifies the app + * instance. If the identifier has been revoked or has expired, this method will + * return a new identifier. + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * @param handler The handler to invoke once the identifier has been fetched. + * In case of error an appropriate error object is returned else + * a valid identifier is returned and a valid identifier for the + * application instance. + */ +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler NS_SWIFT_NAME(getID(handler:)); + +/** + * Resets Instance ID and revokes all tokens. + * + * This method also triggers a request to fetch a new Instance ID and Firebase Messaging scope + * token. Please listen to kFIRInstanceIDTokenRefreshNotification when the new ID and token are + * ready. + * + * This stops the periodic sending of data to the Firebase backend that began when the Instance ID + * was generated. No more data is sent until another library calls Instance ID internally again + * (like FCM, RemoteConfig or Analytics) or user explicitly calls Instance ID APIs to get an + * Instance ID and token again. + */ +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler NS_SWIFT_NAME(deleteID(handler:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h new file mode 100644 index 0000000..78c9ef1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h @@ -0,0 +1,17 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/LICENSE b/PRODUCTNAME/app/Pods/FirebaseInstanceID/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PRODUCTNAME/app/Pods/FirebaseInstanceID/README.md b/PRODUCTNAME/app/Pods/FirebaseInstanceID/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseInstanceID/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMMessageCode.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMMessageCode.h new file mode 100644 index 0000000..4c47838 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMMessageCode.h @@ -0,0 +1,199 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) { + // FIRMessaging+FIRApp.m + kFIRMessagingMessageCodeFIRApp000 = 1000, // I-FCM001000 + kFIRMessagingMessageCodeFIRApp001 = 1001, // I-FCM001001 + // FIRMessaging.m + kFIRMessagingMessageCodeMessagingPrintLibraryVersion = 2000, // I-FCM002000 + kFIRMessagingMessageCodeMessaging001 = 2001, // I-FCM002001 + kFIRMessagingMessageCodeMessaging002 = 2002, // I-FCM002002 - no longer used + kFIRMessagingMessageCodeMessaging003 = 2003, // I-FCM002003 + kFIRMessagingMessageCodeMessaging004 = 2004, // I-FCM002004 + kFIRMessagingMessageCodeMessaging005 = 2005, // I-FCM002005 + kFIRMessagingMessageCodeMessaging006 = 2006, // I-FCM002006 - no longer used + kFIRMessagingMessageCodeMessaging007 = 2007, // I-FCM002007 - no longer used + kFIRMessagingMessageCodeMessaging008 = 2008, // I-FCM002008 - no longer used + kFIRMessagingMessageCodeMessaging009 = 2009, // I-FCM002009 + kFIRMessagingMessageCodeMessaging010 = 2010, // I-FCM002010 + kFIRMessagingMessageCodeMessaging011 = 2011, // I-FCM002011 + kFIRMessagingMessageCodeMessaging012 = 2012, // I-FCM002012 + kFIRMessagingMessageCodeMessaging013 = 2013, // I-FCM002013 + kFIRMessagingMessageCodeMessaging014 = 2014, // I-FCM002014 + kFIRMessagingMessageCodeMessaging015 = 2015, // I-FCM002015 + kFIRMessagingMessageCodeMessaging016 = 2016, // I-FCM002016 - no longer used + kFIRMessagingMessageCodeMessaging017 = 2017, // I-FCM002017 + kFIRMessagingMessageCodeMessaging018 = 2018, // I-FCM002018 + kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented = 2019, // I-FCM002019 + kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenFetch = 2020, // I-FCM002020 + kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenDelete = 2021, // I-FCM002021 + kFIRMessagingMessageCodeAPNSTokenNotAvailableDuringTokenFetch = 2022, // I-FCM002022 + kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented = 2023, // I-FCM002023 + kFIRMessagingMessageCodeTopicFormatIsDeprecated = 2024, + kFIRMessagingMessageCodeDirectChannelConnectionFailed = 2025, + // FIRMessagingClient.m + kFIRMessagingMessageCodeClient000 = 4000, // I-FCM004000 + kFIRMessagingMessageCodeClient001 = 4001, // I-FCM004001 + kFIRMessagingMessageCodeClient002 = 4002, // I-FCM004002 + kFIRMessagingMessageCodeClient003 = 4003, // I-FCM004003 + kFIRMessagingMessageCodeClient004 = 4004, // I-FCM004004 + kFIRMessagingMessageCodeClient005 = 4005, // I-FCM004005 + kFIRMessagingMessageCodeClient006 = 4006, // I-FCM004006 + kFIRMessagingMessageCodeClient007 = 4007, // I-FCM004007 + kFIRMessagingMessageCodeClient008 = 4008, // I-FCM004008 + kFIRMessagingMessageCodeClient009 = 4009, // I-FCM004009 + kFIRMessagingMessageCodeClient010 = 4010, // I-FCM004010 + kFIRMessagingMessageCodeClient011 = 4011, // I-FCM004011 + // FIRMessagingConnection.m + kFIRMessagingMessageCodeConnection000 = 5000, // I-FCM005000 + kFIRMessagingMessageCodeConnection001 = 5001, // I-FCM005001 + kFIRMessagingMessageCodeConnection002 = 5002, // I-FCM005002 + kFIRMessagingMessageCodeConnection003 = 5003, // I-FCM005003 + kFIRMessagingMessageCodeConnection004 = 5004, // I-FCM005004 + kFIRMessagingMessageCodeConnection005 = 5005, // I-FCM005005 + kFIRMessagingMessageCodeConnection006 = 5006, // I-FCM005006 + kFIRMessagingMessageCodeConnection007 = 5007, // I-FCM005007 + kFIRMessagingMessageCodeConnection008 = 5008, // I-FCM005008 + kFIRMessagingMessageCodeConnection009 = 5009, // I-FCM005009 + kFIRMessagingMessageCodeConnection010 = 5010, // I-FCM005010 + kFIRMessagingMessageCodeConnection011 = 5011, // I-FCM005011 + kFIRMessagingMessageCodeConnection012 = 5012, // I-FCM005012 + kFIRMessagingMessageCodeConnection013 = 5013, // I-FCM005013 + kFIRMessagingMessageCodeConnection014 = 5014, // I-FCM005014 + kFIRMessagingMessageCodeConnection015 = 5015, // I-FCM005015 + kFIRMessagingMessageCodeConnection016 = 5016, // I-FCM005016 + kFIRMessagingMessageCodeConnection017 = 5017, // I-FCM005017 + kFIRMessagingMessageCodeConnection018 = 5018, // I-FCM005018 + kFIRMessagingMessageCodeConnection019 = 5019, // I-FCM005019 + kFIRMessagingMessageCodeConnection020 = 5020, // I-FCM005020 + kFIRMessagingMessageCodeConnection021 = 5021, // I-FCM005021 + kFIRMessagingMessageCodeConnection022 = 5022, // I-FCM005022 + kFIRMessagingMessageCodeConnection023 = 5023, // I-FCM005023 + // FIRMessagingContextManagerService.m + kFIRMessagingMessageCodeContextManagerService000 = 6000, // I-FCM006000 + kFIRMessagingMessageCodeContextManagerService001 = 6001, // I-FCM006001 + kFIRMessagingMessageCodeContextManagerService002 = 6002, // I-FCM006002 + kFIRMessagingMessageCodeContextManagerService003 = 6003, // I-FCM006003 + kFIRMessagingMessageCodeContextManagerService004 = 6004, // I-FCM006004 + kFIRMessagingMessageCodeContextManagerService005 = 6005, // I-FCM006005 + // FIRMessagingDataMessageManager.m + kFIRMessagingMessageCodeDataMessageManager000 = 7000, // I-FCM007000 + kFIRMessagingMessageCodeDataMessageManager001 = 7001, // I-FCM007001 + kFIRMessagingMessageCodeDataMessageManager002 = 7002, // I-FCM007002 + kFIRMessagingMessageCodeDataMessageManager003 = 7003, // I-FCM007003 + kFIRMessagingMessageCodeDataMessageManager004 = 7004, // I-FCM007004 + kFIRMessagingMessageCodeDataMessageManager005 = 7005, // I-FCM007005 + kFIRMessagingMessageCodeDataMessageManager006 = 7006, // I-FCM007006 + kFIRMessagingMessageCodeDataMessageManager007 = 7007, // I-FCM007007 + kFIRMessagingMessageCodeDataMessageManager008 = 7008, // I-FCM007008 + kFIRMessagingMessageCodeDataMessageManager009 = 7009, // I-FCM007009 + kFIRMessagingMessageCodeDataMessageManager010 = 7010, // I-FCM007010 + kFIRMessagingMessageCodeDataMessageManager011 = 7011, // I-FCM007011 + kFIRMessagingMessageCodeDataMessageManager012 = 7012, // I-FCM007012 + // FIRMessagingPendingTopicsList.m + kFIRMessagingMessageCodePendingTopicsList000 = 8000, // I-FCM008000 + // FIRMessagingPubSub.m + kFIRMessagingMessageCodePubSub000 = 9000, // I-FCM009000 + kFIRMessagingMessageCodePubSub001 = 9001, // I-FCM009001 + kFIRMessagingMessageCodePubSub002 = 9002, // I-FCM009002 + kFIRMessagingMessageCodePubSub003 = 9003, // I-FCM009003 + // FIRMessagingReceiver.m + kFIRMessagingMessageCodeReceiver000 = 10000, // I-FCM010000 + kFIRMessagingMessageCodeReceiver001 = 10001, // I-FCM010001 + kFIRMessagingMessageCodeReceiver002 = 10002, // I-FCM010002 + kFIRMessagingMessageCodeReceiver003 = 10003, // I-FCM010003 + kFIRMessagingMessageCodeReceiver004 = 10004, // I-FCM010004 - no longer used + kFIRMessagingMessageCodeReceiver005 = 10005, // I-FCM010005 + // FIRMessagingRegistrar.m + kFIRMessagingMessageCodeRegistrar000 = 11000, // I-FCM011000 + // FIRMessagingRemoteNotificationsProxy.m + kFIRMessagingMessageCodeRemoteNotificationsProxy000 = 12000, // I-FCM012000 + kFIRMessagingMessageCodeRemoteNotificationsProxy001 = 12001, // I-FCM012001 + kFIRMessagingMessageCodeRemoteNotificationsProxyAPNSFailed = 12002, // I-FCM012002 + kFIRMessagingMessageCodeRemoteNotificationsProxyMethodNotAdded = 12003, // I-FCM012003 + // FIRMessagingRmq2PersistentStore.m + kFIRMessagingMessageCodeRmq2PersistentStore000 = 13000, // I-FCM013000 + kFIRMessagingMessageCodeRmq2PersistentStore001 = 13001, // I-FCM013001 + kFIRMessagingMessageCodeRmq2PersistentStore002 = 13002, // I-FCM013002 + kFIRMessagingMessageCodeRmq2PersistentStore003 = 13003, // I-FCM013003 + kFIRMessagingMessageCodeRmq2PersistentStore004 = 13004, // I-FCM013004 + kFIRMessagingMessageCodeRmq2PersistentStore005 = 13005, // I-FCM013005 + kFIRMessagingMessageCodeRmq2PersistentStore006 = 13006, // I-FCM013006 + kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingDatabase = 13007, // I-FCM013007 + kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase = 13008, // I-FCM013008 + kFIRMessagingMessageCodeRmq2PersistentStoreInvalidRmqDirectory = 13009, // I-FCM013009 + kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingTable = 13010, // I-FCM013010 + // FIRMessagingRmqManager.m + kFIRMessagingMessageCodeRmqManager000 = 14000, // I-FCM014000 + // FIRMessagingSecureSocket.m + kFIRMessagingMessageCodeSecureSocket000 = 15000, // I-FCM015000 + kFIRMessagingMessageCodeSecureSocket001 = 15001, // I-FCM015001 + kFIRMessagingMessageCodeSecureSocket002 = 15002, // I-FCM015002 + kFIRMessagingMessageCodeSecureSocket003 = 15003, // I-FCM015003 + kFIRMessagingMessageCodeSecureSocket004 = 15004, // I-FCM015004 + kFIRMessagingMessageCodeSecureSocket005 = 15005, // I-FCM015005 + kFIRMessagingMessageCodeSecureSocket006 = 15006, // I-FCM015006 + kFIRMessagingMessageCodeSecureSocket007 = 15007, // I-FCM015007 + kFIRMessagingMessageCodeSecureSocket008 = 15008, // I-FCM015008 + kFIRMessagingMessageCodeSecureSocket009 = 15009, // I-FCM015009 + kFIRMessagingMessageCodeSecureSocket010 = 15010, // I-FCM015010 + kFIRMessagingMessageCodeSecureSocket011 = 15011, // I-FCM015011 + kFIRMessagingMessageCodeSecureSocket012 = 15012, // I-FCM015012 + kFIRMessagingMessageCodeSecureSocket013 = 15013, // I-FCM015013 + kFIRMessagingMessageCodeSecureSocket014 = 15014, // I-FCM015014 + kFIRMessagingMessageCodeSecureSocket015 = 15015, // I-FCM015015 + kFIRMessagingMessageCodeSecureSocket016 = 15016, // I-FCM015016 + // FIRMessagingSyncMessageManager.m + kFIRMessagingMessageCodeSyncMessageManager000 = 16000, // I-FCM016000 + kFIRMessagingMessageCodeSyncMessageManager001 = 16001, // I-FCM016001 + kFIRMessagingMessageCodeSyncMessageManager002 = 16002, // I-FCM016002 + kFIRMessagingMessageCodeSyncMessageManager003 = 16003, // I-FCM016003 + kFIRMessagingMessageCodeSyncMessageManager004 = 16004, // I-FCM016004 + kFIRMessagingMessageCodeSyncMessageManager005 = 16005, // I-FCM016005 + kFIRMessagingMessageCodeSyncMessageManager006 = 16006, // I-FCM016006 + kFIRMessagingMessageCodeSyncMessageManager007 = 16007, // I-FCM016007 + kFIRMessagingMessageCodeSyncMessageManager008 = 16008, // I-FCM016008 + // FIRMessagingTopicOperation.m + kFIRMessagingMessageCodeTopicOption000 = 17000, // I-FCM017000 + kFIRMessagingMessageCodeTopicOption001 = 17001, // I-FCM017001 + kFIRMessagingMessageCodeTopicOption002 = 17002, // I-FCM017002 + kFIRMessagingMessageCodeTopicOptionTopicEncodingFailed = 17003, // I-FCM017003 + kFIRMessagingMessageCodeTopicOperationEmptyResponse = 17004, // I-FCM017004 + // FIRMessagingUtilities.m + kFIRMessagingMessageCodeUtilities000 = 18000, // I-FCM018000 + kFIRMessagingMessageCodeUtilities001 = 18001, // I-FCM018001 + kFIRMessagingMessageCodeUtilities002 = 18002, // I-FCM018002 + // FIRMessagingAnalytics.m + kFIRMessagingMessageCodeAnalytics000 = 19000, // I-FCM019000 + kFIRMessagingMessageCodeAnalytics001 = 19001, // I-FCM019001 + kFIRMessagingMessageCodeAnalytics002 = 19002, // I-FCM019002 + kFIRMessagingMessageCodeAnalytics003 = 19003, // I-FCM019003 + kFIRMessagingMessageCodeAnalytics004 = 19004, // I-FCM019004 + kFIRMessagingMessageCodeAnalytics005 = 19005, // I-FCM019005 + kFIRMessagingMessageCodeAnalyticsInvalidEvent = 19006, // I-FCM019006 + kFIRMessagingMessageCodeAnalytics007 = 19007, // I-FCM019007 + kFIRMessagingMessageCodeAnalyticsCouldNotInvokeAnalyticsLog = 19008, // I-FCM019008 + + // FIRMessagingExtensionHelper.m + kFIRMessagingServiceExtensionImageInvalidURL = 20000, + kFIRMessagingServiceExtensionImageNotDownloaded = 20001, + kFIRMessagingServiceExtensionLocalFileNotCreated = 20002, + kFIRMessagingServiceExtensionImageNotAttached = 20003, + +}; diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging.m new file mode 100644 index 0000000..7e6653b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging.m @@ -0,0 +1,1195 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !__has_feature(objc_arc) +#error FIRMessagingLib should be compiled with ARC. +#endif + +#import "FIRMessaging.h" +#import "FIRMessaging_Private.h" + +#import + +#import "FIRMessagingAnalytics.h" +#import "FIRMessagingClient.h" +#import "FIRMessagingConstants.h" +#import "FIRMessagingContextManagerService.h" +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingExtensionHelper.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPubSub.h" +#import "FIRMessagingReceiver.h" +#import "FIRMessagingRemoteNotificationsProxy.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingSyncMessageManager.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessagingVersionUtilities.h" +#import "FIRMessaging_Private.h" + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import "NSError+FIRMessaging.h" + +static NSString *const kFIRMessagingMessageViaAPNSRootKey = @"aps"; +static NSString *const kFIRMessagingReachabilityHostname = @"www.google.com"; +static NSString *const kFIRMessagingDefaultTokenScope = @"*"; +static NSString *const kFIRMessagingFCMTokenFetchAPNSOption = @"apns_token"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName FIRMessagingSendSuccessNotification = + @"com.firebase.messaging.notif.send-success"; +const NSNotificationName FIRMessagingSendErrorNotification = + @"com.firebase.messaging.notif.send-error"; +const NSNotificationName FIRMessagingMessagesDeletedNotification = + @"com.firebase.messaging.notif.messages-deleted"; +const NSNotificationName FIRMessagingConnectionStateChangedNotification = + @"com.firebase.messaging.notif.connection-state-changed"; +const NSNotificationName FIRMessagingRegistrationTokenRefreshedNotification = + @"com.firebase.messaging.notif.fcm-token-refreshed"; +#else +NSString *const FIRMessagingSendSuccessNotification = + @"com.firebase.messaging.notif.send-success"; +NSString *const FIRMessagingSendErrorNotification = + @"com.firebase.messaging.notif.send-error"; +NSString * const FIRMessagingMessagesDeletedNotification = + @"com.firebase.messaging.notif.messages-deleted"; +NSString * const FIRMessagingConnectionStateChangedNotification = + @"com.firebase.messaging.notif.connection-state-changed"; +NSString * const FIRMessagingRegistrationTokenRefreshedNotification = + @"com.firebase.messaging.notif.fcm-token-refreshed"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled = + @"com.firebase.messaging.auto-init.enabled"; // Auto Init Enabled key stored in NSUserDefaults + +NSString *const kFIRMessagingAPNSTokenType = @"APNSTokenType"; // APNS Token type key stored in user info. + +NSString *const kFIRMessagingPlistAutoInitEnabled = + @"FirebaseMessagingAutoInitEnabled"; // Auto Init Enabled key stored in Info.plist + +@interface FIRMessagingMessageInfo () + +@property(nonatomic, readwrite, assign) FIRMessagingMessageStatus status; + +@end + +@implementation FIRMessagingMessageInfo + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithStatus:(FIRMessagingMessageStatus)status { + self = [super init]; + if (self) { + _status = status; + } + return self; +} + +@end + +#pragma mark - for iOS 10 compatibility +@implementation FIRMessagingRemoteMessage + +- (instancetype)init { + self = [super init]; + if (self) { + _appData = [[NSMutableDictionary alloc] init]; + } + + return self; +} + +@end + +@interface FIRMessaging () + +// FIRApp properties +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; +@property(nonatomic, readwrite, strong) NSString *defaultFcmToken; + +@property(nonatomic, readwrite, strong) FIRInstanceID *instanceID; + +@property(nonatomic, readwrite, assign) BOOL isClientSetup; + +@property(nonatomic, readwrite, strong) FIRMessagingClient *client; +@property(nonatomic, readwrite, strong) GULReachabilityChecker *reachability; +@property(nonatomic, readwrite, strong) FIRMessagingDataMessageManager *dataMessageManager; +@property(nonatomic, readwrite, strong) FIRMessagingPubSub *pubsub; +@property(nonatomic, readwrite, strong) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, strong) FIRMessagingReceiver *receiver; +@property(nonatomic, readwrite, strong) FIRMessagingSyncMessageManager *syncMessageManager; +@property(nonatomic, readwrite, strong) GULUserDefaults *messagingUserDefaults; + +/// Message ID's logged for analytics. This prevents us from logging the same message twice +/// which can happen if the user inadvertently calls `appDidReceiveMessage` along with us +/// calling it implicitly during swizzling. +@property(nonatomic, readwrite, strong) NSMutableSet *loggedMessageIDs; +@property(nonatomic, readwrite, strong) id _Nullable analytics; + +@end + +// Messaging doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRMessagingInstanceProvider +@end + +@interface FIRMessaging () +@end + +@implementation FIRMessaging + ++ (FIRMessaging *)messaging { + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + id instance = + FIR_COMPONENT(FIRMessagingInstanceProvider, defaultApp.container); + + // We know the instance coming from the container is a FIRMessaging instance, cast it and move on. + FIRMessaging *messaging = (FIRMessaging *)instance; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [messaging start]; + }); + return messaging; +} + ++ (FIRMessagingExtensionHelper *)extensionHelper { + static dispatch_once_t once; + static FIRMessagingExtensionHelper *extensionHelper; + dispatch_once(&once, ^{ + extensionHelper = [[FIRMessagingExtensionHelper alloc] init]; + }); + return extensionHelper; +} + +- (instancetype)initWithAnalytics:(nullable id)analytics + withInstanceID:(FIRInstanceID *)instanceID + withUserDefaults:(GULUserDefaults *)defaults { + self = [super init]; + if (self != nil) { + _loggedMessageIDs = [NSMutableSet set]; + _instanceID = instanceID; + _messagingUserDefaults = defaults; + _analytics = analytics; + } + return self; +} + +- (void)dealloc { + [self.reachability stop]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [self teardown]; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-fcm" + withVersion:FIRMessagingCurrentLibraryVersion()]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRDependency *analyticsDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAnalyticsInterop) isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // Ensure it's cached so it returns the same instance every time messaging is called. + *isCacheable = YES; + id analytics = FIR_COMPONENT(FIRAnalyticsInterop, container); + return [[FIRMessaging alloc] initWithAnalytics:analytics + withInstanceID:[FIRInstanceID instanceID] + withUserDefaults:[GULUserDefaults standardUserDefaults]]; + }; + FIRComponent *messagingProvider = + [FIRComponent componentWithProtocol:@protocol(FIRMessagingInstanceProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ analyticsDep ] + creationBlock:creationBlock]; + + return @[ messagingProvider ]; +} + ++ (void)configureWithApp:(FIRApp *)app { + if (!app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeFIRApp001, + @"Firebase Messaging only works with the default app."); + return; + } + [[FIRMessaging messaging] configureMessaging:app]; +} + +- (void)configureMessaging:(FIRApp *)app { + // Swizzle remote-notification-related methods (app delegate and UNUserNotificationCenter) + if ([FIRMessagingRemoteNotificationsProxy canSwizzleMethods]) { + NSString *docsURLString = @"https://firebase.google.com/docs/cloud-messaging/ios/client" + @"#method_swizzling_in_firebase_messaging"; + FIRMessagingLoggerNotice(kFIRMessagingMessageCodeFIRApp000, + @"FIRMessaging Remote Notifications proxy enabled, will swizzle " + @"remote notification receiver handlers. If you'd prefer to manually " + @"integrate Firebase Messaging, add \"%@\" to your Info.plist, " + @"and set it to NO. Follow the instructions at:\n%@\nto ensure " + @"proper integration.", + kFIRMessagingRemoteNotificationsProxyEnabledInfoPlistKey, + docsURLString); + [[FIRMessagingRemoteNotificationsProxy sharedProxy] swizzleMethodsIfPossible]; + } +} + +- (void)start { + // Print the library version for logging. + NSString *currentLibraryVersion = FIRMessagingCurrentLibraryVersion(); + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeMessagingPrintLibraryVersion, + @"FIRMessaging library version %@", + currentLibraryVersion); + + [self setupReceiver]; + + NSString *hostname = kFIRMessagingReachabilityHostname; + self.reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:hostname]; + [self.reachability start]; + + [self setupFileManagerSubDirectory]; + // setup FIRMessaging objects + [self setupRmqManager]; + [self setupClient]; + [self setupSyncMessageManager]; + [self setupDataMessageManager]; + [self setupTopics]; + + self.isClientSetup = YES; + [self setupNotificationListeners]; +} + +- (void)setupFileManagerSubDirectory { + if (![[self class] hasSubDirectory:kFIRMessagingSubDirectoryName]) { + [[self class] createSubDirectory:kFIRMessagingSubDirectoryName]; + } +} + +- (void)setupNotificationListeners { + // To prevent multiple notifications remove self as observer for all events. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + + [center addObserver:self + selector:@selector(didReceiveDefaultInstanceIDToken:) + name:kFIRMessagingFCMTokenNotification + object:nil]; + [center addObserver:self + selector:@selector(defaultInstanceIDTokenWasRefreshed:) + name:kFIRMessagingRegistrationTokenRefreshNotification + object:nil]; + [center addObserver:self + selector:@selector(applicationStateChanged) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + [center addObserver:self + selector:@selector(applicationStateChanged) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; +} + +- (void)setupReceiver { + self.receiver = [[FIRMessagingReceiver alloc] init]; + self.receiver.delegate = self; +} + +- (void)setupClient { + self.client = [[FIRMessagingClient alloc] initWithDelegate:self + reachability:self.reachability + rmq2Manager:self.rmq2Manager]; +} + +- (void)setupDataMessageManager { + self.dataMessageManager = + [[FIRMessagingDataMessageManager alloc] initWithDelegate:self.receiver + client:self.client + rmq2Manager:self.rmq2Manager + syncMessageManager:self.syncMessageManager]; + + [self.dataMessageManager refreshDelayedMessages]; + [self.client setDataMessageManager:self.dataMessageManager]; +} + +- (void)setupRmqManager { + self.rmq2Manager = [[FIRMessagingRmqManager alloc] initWithDatabaseName:@"rmq2"]; + [self.rmq2Manager loadRmqId]; +} + +- (void)setupTopics { + _FIRMessagingDevAssert(self.client, @"Invalid nil client before init pubsub."); + self.pubsub = [[FIRMessagingPubSub alloc] initWithClient:self.client]; +} + +- (void)setupSyncMessageManager { + self.syncMessageManager = + [[FIRMessagingSyncMessageManager alloc] initWithRmqManager:self.rmq2Manager]; + + // Delete the expired messages with a delay. We don't want to block startup with a somewhat + // expensive db call. + FIRMessaging_WEAKIFY(self); + dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)); + dispatch_after(time, dispatch_get_main_queue(), ^{ + FIRMessaging_STRONGIFY(self); + [self.syncMessageManager removeExpiredSyncMessages]; + }); +} + +- (void)teardown { + _FIRMessagingDevAssert([NSThread isMainThread], + @"FIRMessaging should be called from main thread only."); + [self.client teardown]; + self.pubsub = nil; + self.syncMessageManager = nil; + self.rmq2Manager = nil; + self.dataMessageManager = nil; + self.client = nil; + self.isClientSetup = NO; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging001, @"Did successfully teardown"); +} + +#pragma mark - Messages + +- (FIRMessagingMessageInfo *)appDidReceiveMessage:(NSDictionary *)message { + if (!message.count) { + return [[FIRMessagingMessageInfo alloc] initWithStatus:FIRMessagingMessageStatusUnknown]; + } + + // For downstream messages that go via MCS we should strip out this key before sending + // the message to the device. + BOOL isOldMessage = NO; + NSString *messageID = message[kFIRMessagingMessageIDKey]; + if ([messageID length]) { + [self.rmq2Manager saveS2dMessageWithRmqId:messageID]; + + BOOL isSyncMessage = [[self class] isAPNSSyncMessage:message]; + if (isSyncMessage) { + isOldMessage = [self.syncMessageManager didReceiveAPNSSyncMessage:message]; + } + } + // Prevent duplicates by keeping a cache of all the logged messages during each session. + // The duplicates only happen when the 3P app calls `appDidReceiveMessage:` along with + // us swizzling their implementation to call the same method implicitly. + if (!isOldMessage && messageID.length) { + isOldMessage = [self.loggedMessageIDs containsObject:messageID]; + if (!isOldMessage) { + [self.loggedMessageIDs addObject:messageID]; + } + } + + if (!isOldMessage) { + [FIRMessagingAnalytics logMessage:message toAnalytics:_analytics]; + [self handleContextManagerMessage:message]; + [self handleIncomingLinkIfNeededFromMessage:message]; + } + return [[FIRMessagingMessageInfo alloc] initWithStatus:FIRMessagingMessageStatusNew]; +} + +- (BOOL)handleContextManagerMessage:(NSDictionary *)message { + if ([FIRMessagingContextManagerService isContextManagerMessage:message]) { + return [FIRMessagingContextManagerService handleContextManagerMessage:message]; + } + return NO; +} + ++ (BOOL)isAPNSSyncMessage:(NSDictionary *)message { + if ([message[kFIRMessagingMessageViaAPNSRootKey] isKindOfClass:[NSDictionary class]]) { + NSDictionary *aps = message[kFIRMessagingMessageViaAPNSRootKey]; + return [aps[kFIRMessagingMessageAPNSContentAvailableKey] boolValue]; + } + return NO; +} + +- (void)handleIncomingLinkIfNeededFromMessage:(NSDictionary *)message { + NSURL *url = [self linkURLFromMessage:message]; + if (url == nil) { + return; + } + if (![NSThread isMainThread]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self handleIncomingLinkIfNeededFromMessage:message]; + + }); + return; + } + UIApplication *application = FIRMessagingUIApplication(); + if (!application) { + return; + } + id appDelegate = application.delegate; + SEL continueUserActivitySelector = + @selector(application:continueUserActivity:restorationHandler:); + SEL openURLWithOptionsSelector = @selector(application:openURL:options:); + SEL openURLWithSourceApplicationSelector = + @selector(application:openURL:sourceApplication:annotation:); + SEL handleOpenURLSelector = @selector(application:handleOpenURL:); + // Due to FIRAAppDelegateProxy swizzling, this selector will most likely get chosen, whether or + // not the actual application has implemented + // |application:continueUserActivity:restorationHandler:|. A warning will be displayed to the user + // if they haven't implemented it. + if ([NSUserActivity class] != nil && + [appDelegate respondsToSelector:continueUserActivitySelector]) { + NSUserActivity *userActivity = + [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb]; + userActivity.webpageURL = url; + [appDelegate application:application + continueUserActivity:userActivity + restorationHandler:^(NSArray * _Nullable restorableObjects) { + // Do nothing, as we don't support the app calling this block + }]; + + } else if ([appDelegate respondsToSelector:openURLWithOptionsSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [appDelegate application:application openURL:url options:@{}]; +#pragma clang diagnostic pop + + // Similarly, |application:openURL:sourceApplication:annotation:| will also always be called, due + // to the default swizzling done by FIRAAppDelegateProxy in Firebase Analytics + } else if ([appDelegate respondsToSelector:openURLWithSourceApplicationSelector]) { +#if TARGET_OS_IOS +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [appDelegate application:application + openURL:url + sourceApplication:FIRMessagingAppIdentifier() + annotation:@{}]; +#pragma clang diagnostic pop +#endif + } else if ([appDelegate respondsToSelector:handleOpenURLSelector]) { +#if TARGET_OS_IOS +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [appDelegate application:application handleOpenURL:url]; +#pragma clang diagnostic pop +#endif + } +} + +- (NSURL *)linkURLFromMessage:(NSDictionary *)message { + NSString *urlString = message[kFIRMessagingMessageLinkKey]; + if (urlString == nil || ![urlString isKindOfClass:[NSString class]] || urlString.length == 0) { + return nil; + } + NSURL *url = [NSURL URLWithString:urlString]; + return url; +} + +#pragma mark - APNS + +- (NSData *)APNSToken { + return self.apnsTokenData; +} + +- (void)setAPNSToken:(NSData *)APNSToken { + [self setAPNSToken:APNSToken type:FIRMessagingAPNSTokenTypeUnknown]; +} + +- (void)setAPNSToken:(NSData *)apnsToken type:(FIRMessagingAPNSTokenType)type { + if ([apnsToken isEqual:self.apnsTokenData]) { + return; + } + self.apnsTokenData = apnsToken; + + // Notify InstanceID that APNS Token has been set. + NSDictionary *userInfo = @{kFIRMessagingAPNSTokenType : @(type)}; + NSNotification *notification = + [NSNotification notificationWithName:kFIRMessagingAPNSTokenNotification + object:[apnsToken copy] + userInfo:userInfo]; + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; +} + +#pragma mark - FCM + +- (BOOL)isAutoInitEnabled { + // Check storage + id isAutoInitEnabledObject = + [_messagingUserDefaults objectForKey:kFIRMessagingUserDefaultsKeyAutoInitEnabled]; + if (isAutoInitEnabledObject) { + return [isAutoInitEnabledObject boolValue]; + } + + // Check Info.plist + isAutoInitEnabledObject = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRMessagingPlistAutoInitEnabled]; + if (isAutoInitEnabledObject) { + return [isAutoInitEnabledObject boolValue]; + } + + // If none of above exists, we default to the global switch that comes from FIRApp. + return [[FIRApp defaultApp] isDataCollectionDefaultEnabled]; +} + +- (void)setAutoInitEnabled:(BOOL)autoInitEnabled { + BOOL isFCMAutoInitEnabled = [self isAutoInitEnabled]; + [_messagingUserDefaults setBool:autoInitEnabled + forKey:kFIRMessagingUserDefaultsKeyAutoInitEnabled]; + [_messagingUserDefaults synchronize]; + if (!isFCMAutoInitEnabled && autoInitEnabled) { + self.defaultFcmToken = self.instanceID.token; + } +} + +- (NSString *)FCMToken { + NSString *token = self.defaultFcmToken; + if (!token) { + // We may not have received it from Instance ID yet (via NSNotification), so extract it directly + token = self.instanceID.token; + } + return token; +} + +- (void)retrieveFCMTokenForSenderID:(nonnull NSString *)senderID + completion:(nonnull FIRMessagingFCMTokenFetchCompletion)completion { + if (!senderID.length) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenFetch, + @"Sender ID not supplied. It is required for a token fetch, " + @"to identify the sender."); + if (completion) { + NSString *description = @"Couldn't fetch token because a Sender ID was not supplied. A valid " + @"Sender ID is required to fetch an FCM token"; + NSError *error = [NSError fcm_errorWithCode:FIRMessagingErrorInvalidRequest + userInfo:@{NSLocalizedDescriptionKey : description}]; + completion(nil, error); + } + return; + } + NSDictionary *options = nil; + if (self.APNSToken) { + options = @{kFIRMessagingFCMTokenFetchAPNSOption : self.APNSToken}; + } else { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeAPNSTokenNotAvailableDuringTokenFetch, + @"APNS device token not set before retrieving FCM Token for Sender ID " + @"'%@'. Notifications to this FCM Token will not be delivered over APNS." + @"Be sure to re-retrieve the FCM token once the APNS device token is " + @"set.", senderID); + } + [self.instanceID tokenWithAuthorizedEntity:senderID + scope:kFIRMessagingDefaultTokenScope + options:options + handler:completion]; +} + +- (void)deleteFCMTokenForSenderID:(nonnull NSString *)senderID + completion:(nonnull FIRMessagingDeleteFCMTokenCompletion)completion { + if (!senderID.length) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenDelete, + @"Sender ID not supplied. It is required to delete an FCM token."); + if (completion) { + NSString *description = @"Couldn't delete token because a Sender ID was not supplied. A " + @"valid Sender ID is required to delete an FCM token"; + NSError *error = [NSError fcm_errorWithCode:FIRMessagingErrorInvalidRequest + userInfo:@{NSLocalizedDescriptionKey : description}]; + completion(error); + } + return; + } + [self.instanceID deleteTokenWithAuthorizedEntity:senderID + scope:kFIRMessagingDefaultTokenScope + handler:completion]; +} + +#pragma mark - FIRMessagingDelegate helper methods +- (void)setDelegate:(id)delegate { + _delegate = delegate; + [self validateDelegateConformsToTokenAvailabilityMethods]; +} + +// Check if the delegate conforms to |didReceiveRegistrationToken:| +// and display a warning to the developer if not. +// NOTE: Once |didReceiveRegistrationToken:| can be made a required method, this +// check can be removed. +- (void)validateDelegateConformsToTokenAvailabilityMethods { + if (self.delegate && + ![self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented, + @"The object %@ does not respond to " + @"-messaging:didReceiveRegistrationToken:. Please implement " + @"-messaging:didReceiveRegistrationToken: to be provided with an FCM " + @"token.", self.delegate.description); + } +} + +- (void)notifyDelegateOfFCMTokenAvailability { + __weak FIRMessaging *weakSelf = self; + if (![NSThread isMainThread]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf notifyDelegateOfFCMTokenAvailability]; + }); + return; + } + if ([self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) { + [self.delegate messaging:self didReceiveRegistrationToken:self.defaultFcmToken]; + } +} + +#pragma mark - Application State Changes + +- (void)applicationStateChanged { + if (self.shouldEstablishDirectChannel) { + [self updateAutomaticClientConnection]; + } +} + +#pragma mark - Direct Channel + +- (void)setShouldEstablishDirectChannel:(BOOL)shouldEstablishDirectChannel { + if (_shouldEstablishDirectChannel == shouldEstablishDirectChannel) { + return; + } + _shouldEstablishDirectChannel = shouldEstablishDirectChannel; + [self updateAutomaticClientConnection]; +} + +- (BOOL)isDirectChannelEstablished { + return self.client.isConnectionActive; +} + +- (BOOL)shouldBeConnectedAutomatically { + // We require a token from Instance ID + NSString *token = self.defaultFcmToken; + // Only on foreground connections + UIApplication *application = FIRMessagingUIApplication(); + if (!application) { + return NO; + } + UIApplicationState applicationState = application.applicationState; + BOOL shouldBeConnected = _shouldEstablishDirectChannel && + (token.length > 0) && + applicationState == UIApplicationStateActive; + return shouldBeConnected; +} + +- (void)updateAutomaticClientConnection { + if (![NSThread isMainThread]) { + // Call this method from the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateAutomaticClientConnection]; + }); + return; + } + BOOL shouldBeConnected = [self shouldBeConnectedAutomatically]; + if (shouldBeConnected && !self.client.isConnected) { + [self.client connectWithHandler:^(NSError *error) { + if (!error) { + // It means we connected. Fire connection change notification + [self notifyOfDirectChannelConnectionChange]; + } else { + FIRMessagingLoggerError(kFIRMessagingMessageCodeDirectChannelConnectionFailed, + @"Failed to connect to direct channel, error: %@\n", error); + } + }]; + } else if (!shouldBeConnected && self.client.isConnected) { + [self.client disconnect]; + [self notifyOfDirectChannelConnectionChange]; + } +} + +- (void)notifyOfDirectChannelConnectionChange { + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:FIRMessagingConnectionStateChangedNotification object:self]; +} + +#pragma mark - Topics + ++ (NSString *)normalizeTopic:(NSString *)topic { + if (!topic.length) { + return nil; + } + if (![FIRMessagingPubSub hasTopicsPrefix:topic]) { + topic = [FIRMessagingPubSub addPrefixToTopic:topic]; + } + if ([FIRMessagingPubSub isValidTopicWithPrefix:topic]) { + return [topic copy]; + } + return nil; +} + +- (void)subscribeToTopic:(NSString *)topic { + [self subscribeToTopic:topic completion:nil]; +} + +- (void)subscribeToTopic:(NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion { + if ([FIRMessagingPubSub hasTopicsPrefix:topic]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTopicFormatIsDeprecated, + @"Format '%@' is deprecated. Only '%@' should be used in " + @"subscribeToTopic.", + topic, [FIRMessagingPubSub removePrefixFromTopic:topic]); + } + if (!self.defaultFcmToken.length) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeMessaging010, + @"The subscription operation is suspended because you don't have a " + @"token. The operation will resume once you get an FCM token."); + } + NSString *normalizeTopic = [[self class] normalizeTopic:topic]; + if (normalizeTopic.length) { + [self.pubsub subscribeToTopic:normalizeTopic handler:completion]; + return; + } + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging009, + @"Cannot parse topic name %@. Will not subscribe.", topic); + if (completion) { + completion([NSError fcm_errorWithCode:FIRMessagingErrorInvalidTopicName userInfo:nil]); + } +} + +- (void)unsubscribeFromTopic:(NSString *)topic { + [self unsubscribeFromTopic:topic completion:nil]; +} + +- (void)unsubscribeFromTopic:(NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion { + if ([FIRMessagingPubSub hasTopicsPrefix:topic]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTopicFormatIsDeprecated, + @"Format '%@' is deprecated. Only '%@' should be used in " + @"unsubscribeFromTopic.", + topic, [FIRMessagingPubSub removePrefixFromTopic:topic]); + } + if (!self.defaultFcmToken.length) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeMessaging012, + @"The unsubscription operation is suspended because you don't have a " + @"token. The operation will resume once you get an FCM token."); + } + NSString *normalizeTopic = [[self class] normalizeTopic:topic]; + if (normalizeTopic.length) { + [self.pubsub unsubscribeFromTopic:normalizeTopic handler:completion]; + return; + } + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging011, + @"Cannot parse topic name %@. Will not unsubscribe.", topic); + if (completion) { + completion([NSError fcm_errorWithCode:FIRMessagingErrorInvalidTopicName userInfo:nil]); + } +} + +#pragma mark - Send + +- (void)sendMessage:(NSDictionary *)message + to:(NSString *)to + withMessageID:(NSString *)messageID + timeToLive:(int64_t)ttl { + _FIRMessagingDevAssert([to length] != 0, @"Invalid receiver id for FIRMessaging-message"); + + NSMutableDictionary *fcmMessage = [[self class] createFIRMessagingMessageWithMessage:message + to:to + withID:messageID + timeToLive:ttl + delay:0]; + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeMessaging013, @"Sending message: %@ with id: %@", + message, messageID); + [self.dataMessageManager sendDataMessageStanza:fcmMessage]; +} + ++ (NSMutableDictionary *)createFIRMessagingMessageWithMessage:(NSDictionary *)message + to:(NSString *)to + withID:(NSString *)msgID + timeToLive:(int64_t)ttl + delay:(int)delay { + NSMutableDictionary *fcmMessage = [NSMutableDictionary dictionary]; + fcmMessage[kFIRMessagingSendTo] = [to copy]; + fcmMessage[kFIRMessagingSendMessageID] = msgID ? [msgID copy] : @""; + fcmMessage[kFIRMessagingSendTTL] = @(ttl); + fcmMessage[kFIRMessagingSendDelay] = @(delay); + fcmMessage[KFIRMessagingSendMessageAppData] = + [NSMutableDictionary dictionaryWithDictionary:message]; + return fcmMessage; +} + +#pragma mark - IID dependencies + ++ (NSString *)FIRMessagingSDKVersion { + return FIRMessagingCurrentLibraryVersion(); +} + ++ (NSString *)FIRMessagingSDKCurrentLocale { + return [self currentLocale]; +} + +#pragma mark - FIRMessagingReceiverDelegate + +- (void)receiver:(FIRMessagingReceiver *)receiver + receivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { + if ([self.delegate respondsToSelector:@selector(messaging:didReceiveMessage:)]) { + [self appDidReceiveMessage:remoteMessage.appData]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [self.delegate messaging:self didReceiveMessage:remoteMessage]; +#pragma pop + } else { + // Delegate methods weren't implemented, so messages are being dropped, log a warning + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented, + @"FIRMessaging received data-message, but FIRMessagingDelegate's" + @"-messaging:didReceiveMessage: not implemented"); + } +} + +#pragma mark - GULReachabilityDelegate + +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + [self onNetworkStatusChanged]; +} + +#pragma mark - Network + +- (void)onNetworkStatusChanged { + if (![self.client isConnected] && [self isNetworkAvailable]) { + if (self.client.shouldStayConnected) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging014, + @"Attempting to establish direct channel."); + [self.client retryConnectionImmediately:YES]; + } + [self.pubsub scheduleSync:YES]; + } +} + +- (BOOL)isNetworkAvailable { + GULReachabilityStatus status = self.reachability.reachabilityStatus; + return (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); +} + +- (FIRMessagingNetworkStatus)networkType { + GULReachabilityStatus status = self.reachability.reachabilityStatus; + if (![self isNetworkAvailable]) { + return kFIRMessagingReachabilityNotReachable; + } else if (status == kGULReachabilityViaCellular) { + return kFIRMessagingReachabilityReachableViaWWAN; + } else { + return kFIRMessagingReachabilityReachableViaWiFi; + } +} + +#pragma mark - Notifications + +- (void)didReceiveDefaultInstanceIDToken:(NSNotification *)notification { + if (notification.object && ![notification.object isKindOfClass:[NSString class]]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging015, + @"Invalid default FCM token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSString *oldToken = self.defaultFcmToken; + self.defaultFcmToken = [(NSString *)notification.object copy]; + if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) { + [self notifyDelegateOfFCMTokenAvailability]; + } + [self.pubsub scheduleSync:YES]; + if (self.shouldEstablishDirectChannel) { + [self updateAutomaticClientConnection]; + } +} + +- (void)defaultInstanceIDTokenWasRefreshed:(NSNotification *)notification { + // Retrieve the Instance ID default token, and if it is non-nil, post it + NSString *token = self.instanceID.token; + // Sometimes Instance ID doesn't yet have a token, so wait until the default + // token is fetched, and then notify. This ensures that this token should not + // be nil when the developer accesses it. + if (token != nil) { + NSString *oldToken = self.defaultFcmToken; + self.defaultFcmToken = [token copy]; + if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) { + [self notifyDelegateOfFCMTokenAvailability]; + } + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:FIRMessagingRegistrationTokenRefreshedNotification object:nil]; + } +} + +#pragma mark - Application Support Directory + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSString *)pathForSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), + NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[dirPath, subDirectoryName]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging017, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging018, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + +#pragma mark - Locales + ++ (NSString *)currentLocale { + NSArray *locales = [self firebaseLocales]; + NSArray *preferredLocalizations = + [NSBundle preferredLocalizationsFromArray:locales + forPreferences:[NSLocale preferredLanguages]]; + NSString *legalDocsLanguage = [preferredLocalizations firstObject]; + // Use en as the default language + return legalDocsLanguage ? legalDocsLanguage : @"en"; +} + ++ (NSArray *)firebaseLocales { + NSMutableArray *locales = [NSMutableArray array]; + NSDictionary *localesMap = [self firebaselocalesMap]; + for (NSString *key in localesMap) { + [locales addObjectsFromArray:localesMap[key]]; + } + return locales; +} + ++ (NSDictionary *)firebaselocalesMap { + return @{ + // Albanian + @"sq" : @[ @"sq_AL" ], + // Belarusian + @"be" : @[ @"be_BY" ], + // Bulgarian + @"bg" : @[ @"bg_BG" ], + // Catalan + @"ca" : @[ @"ca", @"ca_ES" ], + // Croatian + @"hr" : @[ @"hr", @"hr_HR" ], + // Czech + @"cs" : @[ @"cs", @"cs_CZ" ], + // Danish + @"da" : @[ @"da", @"da_DK" ], + // Estonian + @"et" : @[ @"et_EE" ], + // Finnish + @"fi" : @[ @"fi", @"fi_FI" ], + // Hebrew + @"he" : @[ @"he", @"iw_IL" ], + // Hindi + @"hi" : @[ @"hi_IN" ], + // Hungarian + @"hu" : @[ @"hu", @"hu_HU" ], + // Icelandic + @"is" : @[ @"is_IS" ], + // Indonesian + @"id" : @[ @"id", @"in_ID", @"id_ID" ], + // Irish + @"ga" : @[ @"ga_IE" ], + // Korean + @"ko" : @[ @"ko", @"ko_KR", @"ko-KR" ], + // Latvian + @"lv" : @[ @"lv_LV" ], + // Lithuanian + @"lt" : @[ @"lt_LT" ], + // Macedonian + @"mk" : @[ @"mk_MK" ], + // Malay + @"ms" : @[ @"ms_MY" ], + // Maltese + @"ms" : @[ @"mt_MT" ], + // Polish + @"pl" : @[ @"pl", @"pl_PL", @"pl-PL" ], + // Romanian + @"ro" : @[ @"ro", @"ro_RO" ], + // Russian + @"ru" : @[ @"ru_RU", @"ru", @"ru_BY", @"ru_KZ", @"ru-RU" ], + // Slovak + @"sk" : @[ @"sk", @"sk_SK" ], + // Slovenian + @"sl" : @[ @"sl_SI" ], + // Swedish + @"sv" : @[ @"sv", @"sv_SE", @"sv-SE" ], + // Turkish + @"tr" : @[ @"tr", @"tr-TR", @"tr_TR" ], + // Ukrainian + @"uk" : @[ @"uk", @"uk_UA" ], + // Vietnamese + @"vi" : @[ @"vi", @"vi_VN" ], + // The following are groups of locales or locales that sub-divide a + // language). + // Arabic + @"ar" : @[ + @"ar", + @"ar_DZ", + @"ar_BH", + @"ar_EG", + @"ar_IQ", + @"ar_JO", + @"ar_KW", + @"ar_LB", + @"ar_LY", + @"ar_MA", + @"ar_OM", + @"ar_QA", + @"ar_SA", + @"ar_SD", + @"ar_SY", + @"ar_TN", + @"ar_AE", + @"ar_YE", + @"ar_GB", + @"ar-IQ", + @"ar_US" + ], + // Simplified Chinese + @"zh_Hans" : @[ @"zh_CN", @"zh_SG", @"zh-Hans" ], + // Traditional Chinese + @"zh_Hant" : @[ @"zh_HK", @"zh_TW", @"zh-Hant", @"zh-HK", @"zh-TW" ], + // Dutch + @"nl" : @[ @"nl", @"nl_BE", @"nl_NL", @"nl-NL" ], + // English + @"en" : @[ + @"en", + @"en_AU", + @"en_CA", + @"en_IN", + @"en_IE", + @"en_MT", + @"en_NZ", + @"en_PH", + @"en_SG", + @"en_ZA", + @"en_GB", + @"en_US", + @"en_AE", + @"en-AE", + @"en_AS", + @"en-AU", + @"en_BD", + @"en-CA", + @"en_EG", + @"en_ES", + @"en_GB", + @"en-GB", + @"en_HK", + @"en_ID", + @"en-IN", + @"en_NG", + @"en-PH", + @"en_PK", + @"en-SG", + @"en-US" + ], + // French + + @"fr" : @[ + @"fr", + @"fr_BE", + @"fr_CA", + @"fr_FR", + @"fr_LU", + @"fr_CH", + @"fr-CA", + @"fr-FR", + @"fr_MA" + ], + // German + @"de" : @[ @"de", @"de_AT", @"de_DE", @"de_LU", @"de_CH", @"de-DE" ], + // Greek + @"el" : @[ @"el", @"el_CY", @"el_GR" ], + // Italian + @"it" : @[ @"it", @"it_IT", @"it_CH", @"it-IT" ], + // Japanese + @"ja" : @[ @"ja", @"ja_JP", @"ja_JP_JP", @"ja-JP" ], + // Norwegian + @"no" : @[ @"nb", @"no_NO", @"no_NO_NY", @"nb_NO" ], + // Brazilian Portuguese + @"pt_BR" : @[ @"pt_BR", @"pt-BR" ], + // European Portuguese + @"pt_PT" : @[ @"pt", @"pt_PT", @"pt-PT" ], + // Serbian + @"sr" : @[ + @"sr_BA", + @"sr_ME", + @"sr_RS", + @"sr_Latn_BA", + @"sr_Latn_ME", + @"sr_Latn_RS" + ], + // European Spanish + @"es_ES" : @[ @"es", @"es_ES", @"es-ES" ], + // Mexican Spanish + @"es_MX" : @[ @"es-MX", @"es_MX", @"es_US", @"es-US" ], + // Latin American Spanish + @"es_419" : @[ + @"es_AR", + @"es_BO", + @"es_CL", + @"es_CO", + @"es_CR", + @"es_DO", + @"es_EC", + @"es_SV", + @"es_GT", + @"es_HN", + @"es_NI", + @"es_PA", + @"es_PY", + @"es_PE", + @"es_PR", + @"es_UY", + @"es_VE", + @"es-AR", + @"es-CL", + @"es-CO" + ], + // Thai + @"th" : @[ @"th", @"th_TH", @"th_TH_TH" ], + }; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.h new file mode 100644 index 0000000..13bfab5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides integration between FIRMessaging and Analytics. + * + * All Analytics dependencies should be kept in this class, and missing dependencies should be + * handled gracefully. + * + */ +@interface FIRMessagingAnalytics : NSObject + +/** + * Determine whether a notification has the properties to be loggable to Analytics. + * If so, send the notification. + * @param notification The notification payload from APNs + * @param analytics The class to be used as the receiver of the logging method + */ + ++ (void)logMessage:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.m new file mode 100644 index 0000000..42124be --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.m @@ -0,0 +1,225 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRMessagingAnalytics.h" +#import "FIRMessagingLogger.h" + +#import +#import +#import + +static NSString *const kLogTag = @"FIRMessagingAnalytics"; + +// aps Key +static NSString *const kApsKey = @"aps"; +static NSString *const kApsAlertKey = @"alert"; +static NSString *const kApsSoundKey = @"sound"; +static NSString *const kApsBadgeKey = @"badge"; +static NSString *const kApsContentAvailableKey = @"badge"; + +// Data Key +static NSString *const kDataKey = @"data"; + +// Messaging From Key +static NSString *const kFIRMessagingFromKey = @"from"; + +static NSString *const kFIRParameterLabel = @"label"; + +static NSString *const kReengagementSource = @"Firebase"; +static NSString *const kReengagementMedium = @"notification"; + +// Analytics +static NSString *const kAnalyticsEnabled = @"google.c.a." @"e"; +static NSString *const kAnalyticsComposerIdentifier = @"google.c.a." @"c_id"; +static NSString *const kAnalyticsComposerLabel = @"google.c.a." @"c_l"; +static NSString *const kAnalyticsMessageLabel = @"google.c.a." @"m_l"; +static NSString *const kAnalyticsMessageTimestamp = @"google.c.a." @"ts"; +static NSString *const kAnalyticsMessageUseDeviceTime = @"google.c.a." @"udt"; +static NSString *const kAnalyticsTrackConversions = @"google.c.a." @"tc"; + +@implementation FIRMessagingAnalytics + ++ (BOOL)canLogNotification:(NSDictionary *)notification { + if (!notification.count) { + // Payload is empty + return NO; + } + NSString *isAnalyticsLoggingEnabled = notification[kAnalyticsEnabled]; + if (![isAnalyticsLoggingEnabled isKindOfClass:[NSString class]] || + ![isAnalyticsLoggingEnabled isEqualToString:@"1"]) { + // Analytics logging is not enabled + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics001, + @"Analytics logging is disabled. Do not log event."); + return NO; + } + return YES; +} + ++ (void)logOpenNotification:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + [self logUserPropertyForConversionTracking:notification toAnalytics:analytics]; + [self logEvent:kFIRIEventNotificationOpen +withNotification:notification + toAnalytics:analytics]; +} + ++ (void)logForegroundNotification:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + [self logEvent:kFIRIEventNotificationForeground +withNotification:notification + toAnalytics:analytics]; +} + ++ (void)logEvent:(NSString *)event +withNotification:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + if (!event.length) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalyticsInvalidEvent, + @"Can't log analytics with empty event."); + return; + } + NSMutableDictionary *params = [self paramsForEvent:event withNotification:notification]; + + [analytics logEventWithOrigin:@"fcm" name:event parameters:params]; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics005, + @"%@: Sending event: %@ params: %@", kLogTag, event, params); +} + ++ (NSMutableDictionary *)paramsForEvent:(NSString *)event + withNotification:(NSDictionary *)notification { + NSDictionary *analyticsDataMap = notification; + if (!analyticsDataMap.count) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics000, + @"No data found in notification. Will not log any analytics events."); + return nil; + } + + if (![self canLogNotification:analyticsDataMap]) { + return nil; + } + + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + NSString *composerIdentifier = analyticsDataMap[kAnalyticsComposerIdentifier]; + if ([composerIdentifier isKindOfClass:[NSString class]] && composerIdentifier.length) { + params[kFIRIParameterMessageIdentifier] = [composerIdentifier copy]; + } + + NSString *composerLabel = analyticsDataMap[kAnalyticsComposerLabel]; + if ([composerLabel isKindOfClass:[NSString class]] && composerLabel.length) { + params[kFIRIParameterMessageName] = [composerLabel copy]; + } + + NSString *messageLabel = analyticsDataMap[kAnalyticsMessageLabel]; + if ([messageLabel isKindOfClass:[NSString class]] && messageLabel.length) { + params[kFIRParameterLabel] = [messageLabel copy]; + } + + NSString *from = analyticsDataMap[kFIRMessagingFromKey]; + if ([from isKindOfClass:[NSString class]] && [from containsString:@"/topics/"]) { + params[kFIRIParameterTopic] = [from copy]; + } + + id timestamp = analyticsDataMap[kAnalyticsMessageTimestamp]; + if ([timestamp respondsToSelector:@selector(longLongValue)]) { + int64_t timestampValue = [timestamp longLongValue]; + if (timestampValue != 0) { + params[kFIRIParameterMessageTime] = @(timestampValue); + } + } + + if (analyticsDataMap[kAnalyticsMessageUseDeviceTime]) { + params[kFIRIParameterMessageDeviceTime] = analyticsDataMap[kAnalyticsMessageUseDeviceTime]; + } + + return params; +} + ++ (void)logUserPropertyForConversionTracking:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + NSInteger shouldTrackConversions = [notification[kAnalyticsTrackConversions] integerValue]; + if (shouldTrackConversions != 1) { + return; + } + + NSString *composerIdentifier = notification[kAnalyticsComposerIdentifier]; + if ([composerIdentifier isKindOfClass:[NSString class]] && composerIdentifier.length) { + // Set user property for event. + [analytics setUserPropertyWithOrigin:@"fcm" + name:kFIRIUserPropertyLastNotification + value:composerIdentifier]; + + // Set the re-engagement attribution properties. + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:3]; + params[kFIRIParameterSource] = kReengagementSource; + params[kFIRIParameterMedium] = kReengagementMedium; + params[kFIRIParameterCampaign] = composerIdentifier; + [analytics logEventWithOrigin:@"fcm" name:kFIRIEventFirebaseCampaign parameters:params]; + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics003, + @"%@: Sending event: %@ params: %@", kLogTag, + kFIRIEventFirebaseCampaign, params); + + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics004, + @"%@: Failed to set user property: %@ value: %@", kLogTag, + kFIRIUserPropertyLastNotification, composerIdentifier); + } +} + ++ (void)logMessage:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + if (![self canLogNotification:notification]) { + return; + } + + UIApplication *application = [self currentUIApplication]; + if (!application) { + return; + } + UIApplicationState applicationState = application.applicationState; + switch (applicationState) { + case UIApplicationStateInactive: + // App was either in background(suspended) or inactive and user tapped on a display + // notification. + [self logOpenNotification:notification toAnalytics:analytics]; + break; + + case UIApplicationStateActive: + // App was in foreground when it received the notification. + [self logForegroundNotification:notification toAnalytics:analytics]; + break; + + default: + // Only a silent notification (i.e. 'content-available' is true) can be received while the app + // is in the background. These messages aren't loggable anyway. + break; + } +} + ++ (UIApplication *)currentUIApplication { + Class applicationClass = nil; + if (![GULAppEnvironmentUtil isAppExtension]) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + return [applicationClass sharedApplication]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.h new file mode 100644 index 0000000..d7c3451 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Register the device with Checkin Service and get back the `authID`, `secret token` etc. for the + * client. Checkin results are cached and periodically refreshed to + * prevent them from being stale. Each client needs to register with checkin before registering + * with FIRMessaging. + */ +@interface FIRMessagingCheckinService : NSObject + +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; +@property(nonatomic, readonly, strong) NSString *versionInfo; +@property(nonatomic, readonly, assign) BOOL hasValidCheckinInfo; + +/** + * Verify if valid checkin preferences have been loaded in memory. + * + * @return YES if valid checkin preferences exist in memory else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Try to load prefetched checkin preferences from the cache. This supports the use case where + * InstanceID library has already obtained a valid checkin and we should be using that. + * + * This should be used as a last gasp effort to retreive any cached checkin preferences before + * hitting the FIRMessaging backend to retrieve new preferences. + * + * Note this is only required because InstanceID and FIRMessaging both require checkin preferences which + * need to be synced with each other. + * + * @return YES if successfully loaded cached checkin preferences into memory else NO. + */ +- (BOOL)tryToLoadPrefetchedCheckinPreferences; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.m new file mode 100644 index 0000000..9dad847 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.m @@ -0,0 +1,132 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingCheckinService.h" + +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +@interface FIRMessagingCheckinService () + +// This property is of type FIRInstanceIDCheckinPreferences, if InstanceID was directly linkable +@property(nonatomic, readwrite, strong) id checkinPreferences; + +@end + +@implementation FIRMessagingCheckinService; + +#pragma mark - Reflection-Based Getter Functions + +// Encapsulates the -hasValidCheckinInfo method of FIRInstanceIDCheckinPreferences +BOOL FIRMessagingCheckinService_hasValidCheckinInfo(id checkinPreferences) { + SEL hasValidCheckinInfoSelector = NSSelectorFromString(@"hasValidCheckinInfo"); + if (![checkinPreferences respondsToSelector:hasValidCheckinInfoSelector]) { + // Can't check hasValidCheckinInfo + return NO; + } + + // Since hasValidCheckinInfo returns a BOOL, use NSInvocation + NSMethodSignature *methodSignature = + [[checkinPreferences class] instanceMethodSignatureForSelector:hasValidCheckinInfoSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + invocation.selector = hasValidCheckinInfoSelector; + invocation.target = checkinPreferences; + [invocation invoke]; + BOOL returnValue; + [invocation getReturnValue:&returnValue]; + return returnValue; +} + +// Returns a non-scalar (id) object based on the property name +id FIRMessagingCheckinService_propertyNamed(id checkinPreferences, NSString *propertyName) { + SEL propertyGetterSelector = NSSelectorFromString(propertyName); + if ([checkinPreferences respondsToSelector:propertyGetterSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + return [checkinPreferences performSelector:propertyGetterSelector]; +#pragma clang diagnostic pop + } + return nil; +} + +#pragma mark - Methods + +- (BOOL)tryToLoadPrefetchedCheckinPreferences { + Class instanceIDClass = NSClassFromString(@"FIRInstanceID"); + if (!instanceIDClass) { + // InstanceID is not linked + return NO; + } + + // [FIRInstanceID instanceID] + SEL instanceIDSelector = NSSelectorFromString(@"instanceID"); + if (![instanceIDClass respondsToSelector:instanceIDSelector]) { + return NO; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id instanceID = [instanceIDClass performSelector:instanceIDSelector]; +#pragma clang diagnostic pop + if (!instanceID) { + // Instance ID singleton not available + return NO; + } + + // [[FIRInstanceID instanceID] cachedCheckinPreferences] + SEL cachedCheckinPrefsSelector = NSSelectorFromString(@"cachedCheckinPreferences"); + if (![instanceID respondsToSelector:cachedCheckinPrefsSelector]) { + // cachedCheckinPreferences is not accessible + return NO; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id checkinPreferences = [instanceID performSelector:cachedCheckinPrefsSelector]; +#pragma clang diagnostic pop + if (!checkinPreferences) { + // No cached checkin prefs + return NO; + } + + BOOL hasValidInfo = FIRMessagingCheckinService_hasValidCheckinInfo(checkinPreferences); + if (hasValidInfo) { + self.checkinPreferences = checkinPreferences; + } + return hasValidInfo; +} + +#pragma mark - API + +- (NSString *)deviceAuthID { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"deviceID"); +} + +- (NSString *)secretToken { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"secretToken"); +} + +- (NSString *)versionInfo { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"versionInfo"); +} + +- (NSString *)digest { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"digest"); +} + +- (BOOL)hasValidCheckinInfo { + return FIRMessagingCheckinService_hasValidCheckinInfo(self.checkinPreferences); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.h new file mode 100644 index 0000000..98337a3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" + +@class GULReachabilityChecker; +@class GPBMessage; + +@class FIRMessagingConnection; +@class FIRMessagingDataMessageManager; +@class FIRMessagingRmqManager; + +/** + * Callback to handle MCS connection requests. + * + * @param error The error object if any while trying to connect with MCS else nil. + */ +typedef void(^FIRMessagingConnectCompletionHandler)(NSError *error); + +@protocol FIRMessagingClientDelegate + +@end + +/** + * The client handles the subscribe/unsubscribe for an unregistered senderID + * and device. It also manages the FIRMessaging data connection, the exponential backoff + * algorithm in case of registration failures, sign in failures and unregister + * failures. It also handles the reconnect logic if the FIRMessaging connection is + * broken off by some error during an active session. + */ +@interface FIRMessagingClient : NSObject + +@property(nonatomic, readonly, strong) FIRMessagingConnection *connection; +@property(nonatomic, readwrite, weak) FIRMessagingDataMessageManager *dataMessageManager; + +// Designated initializer +- (instancetype)initWithDelegate:(id)delegate + reachability:(GULReachabilityChecker *)reachability + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager; + +- (void)teardown; + +- (void)cancelAllRequests; + +#pragma mark - FIRMessaging subscribe + +/** + * Update the subscription associated with the given token and topic. + * + * For a to-be-created subscription we check if the client is already + * subscribed to the topic or not. If subscribed we should have the + * subscriptionID in the cache and we return from there itself, else we call + * the FIRMessaging backend to create a new subscription for the topic for this client. + * + * For delete subscription requests we delete the stored subscription in the + * client and then invoke the FIRMessaging backend to delete the existing subscription + * completely. + * + * @param token The token associated with the device. + * @param topic The topic for which the subscription should be updated. + * @param options The options to be passed in to the subscription request. + * @param shouldDelete If YES this would delete the subscription from the cache + * and also let the FIRMessaging backend know that we need to delete + * the subscriptionID associated with this topic. + * If NO we try to create a new subscription for the given + * token and topic. + * @param handler The handler to invoke once the subscription request + * finishes. + */ +- (void)updateSubscriptionWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler; + +#pragma mark - MCS Connection + +/** + * Create a MCS connection. + * + * @param handler The handler to be invokend once the connection is setup. If + * setting up the connection fails we invoke the handler with + * an appropriate error object. + */ +- (void)connectWithHandler:(FIRMessagingConnectCompletionHandler)handler; + +/** + * Disconnect the current MCS connection. If there is no valid connection this + * should be a NO-OP. + */ +- (void)disconnect; + +#pragma mark - MCS Connection State + +/** + * If we are connected to MCS or not. This doesn't take into account the fact if + * the client has been signed in(verified) by MCS. + * + * @return YES if we are signed in or connecting and trying to sign-in else NO. + */ +@property(nonatomic, readonly) BOOL isConnected; + +/** + * If we have an active MCS connection + * + * @return YES if we have an active MCS connection else NO. + */ +@property(nonatomic, readonly) BOOL isConnectionActive; + +/** + * If we should be connected to MCS + * + * @return YES if we have attempted a connection and not requested to disconect. + */ +@property(nonatomic, readonly) BOOL shouldStayConnected; + +/** + * Schedule a retry to connect to MCS. If `immediately` is `YES` try to + * schedule a retry now else retry with some delay. + * + * @param immediately Should retry right now. + */ +- (void)retryConnectionImmediately:(BOOL)immediately; + +#pragma mark - Messages + +/** + * Send a message over the MCS connection. + * + * @param message Message to be sent. + */ +- (void)sendMessage:(GPBMessage *)message; + +/** + * Send message if we have an active MCS connection. If not cache the message + * for this session and in case we are able to re-establish the connection try + * again else drop it. This should only be used for TTL=0 messages for now. + * + * @param message Message to be sent. + */ +- (void)sendOnConnectOrDrop:(GPBMessage *)message; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.m new file mode 100644 index 0000000..9d8c558 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.m @@ -0,0 +1,506 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingClient.h" + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingConnection.h" +#import "FIRMessagingConstants.h" +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingRegistrar.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingTopicsCommon.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +static const NSTimeInterval kConnectTimeoutInterval = 40.0; +static const NSTimeInterval kReconnectDelayInSeconds = 2 * 60; // 2 minutes + +static const NSUInteger kMaxRetryExponent = 10; // 2^10 = 1024 seconds ~= 17 minutes + +static NSString *const kFIRMessagingMCSServerHost = @"mtalk.google.com"; +static NSUInteger const kFIRMessagingMCSServerPort = 5228; + +// register device with checkin +typedef void(^FIRMessagingRegisterDeviceHandler)(NSError *error); + +static NSString *FIRMessagingServerHost() { + static NSString *serverHost = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *environment = [[NSProcessInfo processInfo] environment]; + NSString *customServerHostAndPort = environment[@"FCM_MCS_HOST"]; + NSString *host = [customServerHostAndPort componentsSeparatedByString:@":"].firstObject; + if (host) { + serverHost = host; + } else { + serverHost = kFIRMessagingMCSServerHost; + } + }); + return serverHost; +} + +static NSUInteger FIRMessagingServerPort() { + static NSUInteger serverPort = kFIRMessagingMCSServerPort; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *environment = [[NSProcessInfo processInfo] environment]; + NSString *customServerHostAndPort = environment[@"FCM_MCS_HOST"]; + NSArray *components = [customServerHostAndPort componentsSeparatedByString:@":"]; + NSUInteger port = (NSUInteger)[components.lastObject integerValue]; + if (port != 0) { + serverPort = port; + } + }); + return serverPort; +} + +@interface FIRMessagingClient () + +@property(nonatomic, readwrite, weak) id clientDelegate; +@property(nonatomic, readwrite, strong) FIRMessagingConnection *connection; +@property(nonatomic, readwrite, strong) FIRMessagingRegistrar *registrar; + +@property(nonatomic, readwrite, strong) NSString *senderId; + +// FIRMessagingService owns these instances +@property(nonatomic, readwrite, weak) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, weak) GULReachabilityChecker *reachability; + +@property(nonatomic, readwrite, assign) int64_t lastConnectedTimestamp; +@property(nonatomic, readwrite, assign) int64_t lastDisconnectedTimestamp; +@property(nonatomic, readwrite, assign) NSUInteger connectRetryCount; + +// Should we stay connected to MCS or not. Should be YES throughout the lifetime +// of a MCS connection. If set to NO it signifies that an existing MCS connection +// should be disconnected. +@property(nonatomic, readwrite, assign) BOOL stayConnected; +@property(nonatomic, readwrite, assign) NSTimeInterval connectionTimeoutInterval; + +// Used if the MCS connection suddenly breaksdown in the middle and we want to reconnect +// with some permissible delay we schedule a reconnect and set it to YES and when it's +// scheduled this will be set back to NO. +@property(nonatomic, readwrite, assign) BOOL didScheduleReconnect; + +// handlers +@property(nonatomic, readwrite, copy) FIRMessagingConnectCompletionHandler connectHandler; + +@end + +@implementation FIRMessagingClient + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithDelegate:(id)delegate + reachability:(GULReachabilityChecker *)reachability + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager { + self = [super init]; + if (self) { + _reachability = reachability; + _clientDelegate = delegate; + _rmq2Manager = rmq2Manager; + _registrar = [[FIRMessagingRegistrar alloc] init]; + _connectionTimeoutInterval = kConnectTimeoutInterval; + // Listen for checkin fetch notifications, as connecting to MCS may have failed due to + // missing checkin info (while it was being fetched). + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(checkinFetched:) + name:kFIRMessagingCheckinFetchedNotification + object:nil]; + } + return self; +} + +- (void)teardown { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient000, @""); + self.stayConnected = NO; + + // Clear all the handlers + self.connectHandler = nil; + + [self.connection teardown]; + + // Stop all subscription requests + [self.registrar cancelAllRequests]; + + _FIRMessagingDevAssert(self.connection.state == kFIRMessagingConnectionNotConnected, @"Did not disconnect"); + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)cancelAllRequests { + // Stop any checkin requests or any subscription requests + [self.registrar cancelAllRequests]; + + // Stop any future connection requests to MCS + if (self.stayConnected && self.isConnected && !self.isConnectionActive) { + self.stayConnected = NO; + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + } +} + +#pragma mark - FIRMessaging subscribe + +- (void)updateSubscriptionWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler { + + _FIRMessagingDevAssert(handler != nil, @"Invalid handler to FIRMessaging subscribe"); + + FIRMessagingTopicOperationCompletion completion = ^void(NSError *error) { + if (error) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeClient001, @"Failed to subscribe to topic %@", + error); + } else { + if (shouldDelete) { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient002, + @"Successfully unsubscribed from topic %@", topic); + } else { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient003, + @"Successfully subscribed to topic %@", topic); + } + } + handler(error); + }; + + [self.registrar updateSubscriptionToTopic:topic + withToken:token + options:options + shouldDelete:shouldDelete + handler:completion]; +} + +#pragma mark - MCS Connection + +- (BOOL)isConnected { + return self.stayConnected && self.connection.state != kFIRMessagingConnectionNotConnected; +} + +- (BOOL)isConnectionActive { + return self.stayConnected && self.connection.state == kFIRMessagingConnectionSignedIn; +} + +- (BOOL)shouldStayConnected { + return self.stayConnected; +} + +- (void)retryConnectionImmediately:(BOOL)immediately { + // Do not connect to an invalid host or an invalid port + if (!self.stayConnected || !self.connection.host || self.connection.port == 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient004, + @"FIRMessaging connection will not reconnect to MCS. " + @"Stay connected: %d", + self.stayConnected); + return; + } + if (self.isConnectionActive) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient005, + @"FIRMessaging Connection skip retry, active"); + // already connected and logged in. + // Heartbeat alarm is set and will force close the connection + return; + } + if (self.isConnected) { + // already connected and logged in. + // Heartbeat alarm is set and will force close the connection + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient006, + @"FIRMessaging Connection skip retry, connected"); + return; + } + + if (immediately) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient007, + @"Try to connect to MCS immediately"); + [self tryToConnect]; + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient008, @"Try to connect to MCS lazily"); + // Avoid all the other logic that we have in other clients, since this would always happen + // when the app is in the foreground and since the FIRMessaging connection isn't shared with any other + // app we can be more aggressive in reconnections + if (!self.didScheduleReconnect) { + FIRMessaging_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(kReconnectDelayInSeconds * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRMessaging_STRONGIFY(self); + self.didScheduleReconnect = NO; + [self tryToConnect]; + }); + + self.didScheduleReconnect = YES; + } + } +} + +- (void)connectWithHandler:(FIRMessagingConnectCompletionHandler)handler { + if (self.isConnected) { + NSError *error = [NSError fcm_errorWithCode:kFIRMessagingErrorCodeAlreadyConnected + userInfo:@{ + NSLocalizedFailureReasonErrorKey: @"FIRMessaging is already connected", + }]; + handler(error); + return; + } + self.lastDisconnectedTimestamp = FIRMessagingCurrentTimestampInMilliseconds(); + self.connectHandler = handler; + [self connect]; +} + +- (void)connect { + // reset retry counts + self.connectRetryCount = 0; + + if (self.isConnected) { + return; + } + + self.stayConnected = YES; + if (![self.registrar tryToLoadValidCheckinInfo]) { + // Checkin info is not available. This may be due to the checkin still being fetched. + if (self.connectHandler) { + NSError *error = [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeMissingDeviceID]; + self.connectHandler(error); + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient009, + @"Failed to connect to MCS. No deviceID and secret found."); + // Return for now. If checkin is, in fact, retrieved, the + // |kFIRMessagingCheckinFetchedNotification| will be fired. + return; + } + [self setupConnectionAndConnect]; +} + +- (void)disconnect { + // user called disconnect + // We don't want to connect later even if no network is available. + [self disconnectWithTryToConnectLater:NO]; +} + +/** + * Disconnect the current client connection. Also explicitly stop and connction retries. + * + * @param tryToConnectLater If YES will try to connect later when sending upstream messages + * else if NO do not connect again until user explicitly calls + * connect. + */ +- (void)disconnectWithTryToConnectLater:(BOOL)tryToConnectLater { + + self.stayConnected = tryToConnectLater; + [self.connection signOut]; + _FIRMessagingDevAssert(self.connection.state == kFIRMessagingConnectionNotConnected, + @"FIRMessaging connection did not disconnect"); + + // since we can disconnect while still trying to establish the connection it's required to + // cancel all performSelectors else the object might be retained + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(tryToConnect) + object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(didConnectTimeout) + object:nil]; + self.connectHandler = nil; +} + +#pragma mark - Checkin Notification +- (void)checkinFetched:(NSNotification *)notification { + // A failed checkin may have been the reason for the connection failure. Attempt a connection + // if the checkin fetched notification is fired. + if (self.stayConnected && !self.isConnected) { + [self connect]; + } +} + +#pragma mark - Messages + +- (void)sendMessage:(GPBMessage *)message { + [self.connection sendProto:message]; +} + +- (void)sendOnConnectOrDrop:(GPBMessage *)message { + [self.connection sendOnConnectOrDrop:message]; +} + +#pragma mark - FIRMessagingConnectionDelegate + +- (void)connection:(FIRMessagingConnection *)fcmConnection + didCloseForReason:(FIRMessagingConnectionCloseReason)reason { + + self.lastDisconnectedTimestamp = FIRMessagingCurrentTimestampInMilliseconds(); + + if (reason == kFIRMessagingConnectionCloseReasonSocketDisconnected) { + // Cancel the not-yet-triggered timeout task before rescheduling, in case the previous sign in + // failed, due to a connection error caused by bad network. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(didConnectTimeout) + object:nil]; + } + if (self.stayConnected) { + [self scheduleConnectRetry]; + } +} + +- (void)didLoginWithConnection:(FIRMessagingConnection *)fcmConnection { + // Cancel the not-yet-triggered timeout task. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(didConnectTimeout) + object:nil]; + self.connectRetryCount = 0; + self.lastConnectedTimestamp = FIRMessagingCurrentTimestampInMilliseconds(); + + + [self.dataMessageManager setDeviceAuthID:self.registrar.deviceAuthID + secretToken:self.registrar.secretToken]; + if (self.connectHandler) { + self.connectHandler(nil); + // notified the third party app with the registrationId. + // we don't want them to know about the connection status and how it changes + // so remove this handler + self.connectHandler = nil; + } +} + +- (void)connectionDidRecieveMessage:(GtalkDataMessageStanza *)message { + NSDictionary *parsedMessage = [self.dataMessageManager processPacket:message]; + if ([parsedMessage count]) { + [self.dataMessageManager didReceiveParsedMessage:parsedMessage]; + } +} + +- (int)connectionDidReceiveAckForRmqIds:(NSArray *)rmqIds { + NSSet *rmqIDSet = [NSSet setWithArray:rmqIds]; + NSMutableArray *messagesSent = [NSMutableArray arrayWithCapacity:rmqIds.count]; + [self.rmq2Manager scanWithRmqMessageHandler:nil + dataMessageHandler:^(int64_t rmqId, GtalkDataMessageStanza *stanza) { + NSString *rmqIdString = [NSString stringWithFormat:@"%lld", rmqId]; + if ([rmqIDSet containsObject:rmqIdString]) { + [messagesSent addObject:stanza]; + } + }]; + for (GtalkDataMessageStanza *message in messagesSent) { + [self.dataMessageManager didSendDataMessageStanza:message]; + } + return [self.rmq2Manager removeRmqMessagesWithRmqIds:rmqIds]; +} + +#pragma mark - Private + +- (void)setupConnectionAndConnect { + [self setupConnection]; + [self tryToConnect]; +} + +- (void)setupConnection { + NSString *host = FIRMessagingServerHost(); + NSUInteger port = FIRMessagingServerPort(); + _FIRMessagingDevAssert([host length] > 0 && port != 0, @"Invalid port or host"); + + if (self.connection != nil) { + // if there is an old connection, explicitly sign it off. + [self.connection signOut]; + self.connection.delegate = nil; + } + self.connection = [[FIRMessagingConnection alloc] initWithAuthID:self.registrar.deviceAuthID + token:self.registrar.secretToken + host:host + port:port + runLoop:[NSRunLoop mainRunLoop] + rmq2Manager:self.rmq2Manager + fcmManager:self.dataMessageManager]; + self.connection.delegate = self; +} + +- (void)tryToConnect { + if (!self.stayConnected) { + return; + } + + // Cancel any other pending signin requests. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(tryToConnect) + object:nil]; + + // Do not re-sign in if there is already a connection in progress. + if (self.connection.state != kFIRMessagingConnectionNotConnected) { + return; + } + + _FIRMessagingDevAssert(self.registrar.deviceAuthID.length > 0 && + self.registrar.secretToken.length > 0 && + self.connection != nil, + @"Invalid state cannot connect"); + + self.connectRetryCount = MIN(kMaxRetryExponent, self.connectRetryCount + 1); + [self performSelector:@selector(didConnectTimeout) + withObject:nil + afterDelay:self.connectionTimeoutInterval]; + [self.connection signIn]; +} + +- (void)didConnectTimeout { + _FIRMessagingDevAssert(self.connection.state != kFIRMessagingConnectionSignedIn, + @"Invalid state for MCS connection"); + + if (self.stayConnected) { + [self.connection signOut]; + [self scheduleConnectRetry]; + } +} + +#pragma mark - Schedulers + +- (void)scheduleConnectRetry { + GULReachabilityStatus status = self.reachability.reachabilityStatus; + BOOL isReachable = (status == kGULReachabilityViaWifi || status == kGULReachabilityViaCellular); + if (!isReachable) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient010, + @"Internet not reachable when signing into MCS during a retry"); + + FIRMessagingConnectCompletionHandler handler = [self.connectHandler copy]; + // disconnect before issuing a callback + [self disconnectWithTryToConnectLater:YES]; + NSError *error = + [NSError errorWithDomain:@"No internet available, cannot connect to FIRMessaging" + code:kFIRMessagingErrorCodeNetwork + userInfo:nil]; + if (handler) { + handler(error); + self.connectHandler = nil; + } + return; + } + + NSUInteger retryInterval = [self nextRetryInterval]; + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient011, + @"Failed to sign in to MCS, retry in %lu seconds", + _FIRMessaging_UL(retryInterval)); + [self performSelector:@selector(tryToConnect) withObject:nil afterDelay:retryInterval]; +} + +- (NSUInteger)nextRetryInterval { + return 1u << self.connectRetryCount; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.h new file mode 100644 index 0000000..8f22290 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRMessagingCodedInputStream : NSObject + +@property(nonatomic, readonly, assign) size_t offset; + +- (instancetype)initWithData:(NSData *)data; +- (BOOL)readTag:(int8_t *)tag; +- (BOOL)readLength:(int32_t *)length; +- (NSData *)readDataWithLength:(uint32_t)length; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.m new file mode 100644 index 0000000..82c0677 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.m @@ -0,0 +1,142 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingCodedInputStream.h" +#import "FIRMessagingDefines.h" + +typedef struct { + const void *bytes; + size_t bufferSize; + size_t bufferPos; +} BufferState; + +static BOOL CheckSize(BufferState *state, size_t size) { + size_t newSize = state->bufferPos + size; + if (newSize > state->bufferSize) { + return NO; + } + return YES; +} + +static BOOL ReadRawByte(BufferState *state, int8_t *output) { + _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters"); + + if (CheckSize(state, sizeof(int8_t))) { + *output = ((int8_t *)state->bytes)[state->bufferPos++]; + return YES; + } + return NO; +} + +static BOOL ReadRawVarInt32(BufferState *state, int32_t *output) { + _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters"); + + int8_t tmp = 0; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + *output = tmp; + return YES; + } + int32_t result = tmp & 0x7f; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + result |= tmp << 28; + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; ++i) { + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + *output = result; + return YES; + } + } + return NO; + } + } + } + } + *output = result; + return YES; +} + +@interface FIRMessagingCodedInputStream() + +@property(nonatomic, readwrite, strong) NSData *buffer; +@property(nonatomic, readwrite, assign) BufferState state; + +@end + +@implementation FIRMessagingCodedInputStream; + +- (instancetype)initWithData:(NSData *)data { + self = [super init]; + if (self) { + _buffer = data; + _state.bytes = _buffer.bytes; + _state.bufferSize = _buffer.length; + } + return self; +} + +- (size_t)offset { + return _state.bufferPos; +} + +- (BOOL)readTag:(int8_t *)tag { + return ReadRawByte(&_state, tag); +} + +- (BOOL)readLength:(int32_t *)length { + return ReadRawVarInt32(&_state, length); +} + +- (NSData *)readDataWithLength:(uint32_t)length { + if (!CheckSize(&_state, length)) { + return nil; + } + const void *bytesToRead = _state.bytes + _state.bufferPos; + NSData *result = [NSData dataWithBytes:bytesToRead length:length]; + _state.bufferPos += length; + return result; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.h new file mode 100644 index 0000000..25a018c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.h @@ -0,0 +1,106 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRMessagingConnection; +@class FIRMessagingDataMessageManager; +@class FIRMessagingRmqManager; + +@class GtalkDataMessageStanza; +@class GPBMessage; + +typedef void (^FIRMessagingMessageHandler)(NSDictionary *); + +typedef NS_ENUM(NSUInteger, FIRMessagingConnectionState) { + kFIRMessagingConnectionNotConnected = 0, + kFIRMessagingConnectionConnecting, + kFIRMessagingConnectionConnected, + kFIRMessagingConnectionSignedIn, +}; + +typedef NS_ENUM(NSUInteger, FIRMessagingConnectionCloseReason) { + kFIRMessagingConnectionCloseReasonSocketDisconnected = 0, + kFIRMessagingConnectionCloseReasonTimeout, + kFIRMessagingConnectionCloseReasonUserDisconnect, +}; + +@protocol FIRMessagingConnectionDelegate + +- (void)connection:(FIRMessagingConnection *)fcmConnection + didCloseForReason:(FIRMessagingConnectionCloseReason)reason; +- (void)didLoginWithConnection:(FIRMessagingConnection *)fcmConnection; +- (void)connectionDidRecieveMessage:(GtalkDataMessageStanza *)message; +/** + * Called when a stream ACK or a selective ACK are received - this indicates the + * message has been received by MCS. + * @return The count of rmqIds deleted from the client RMQ store. + */ +- (int)connectionDidReceiveAckForRmqIds:(NSArray *)rmqIds; + +@end + + +/** + * This class maintains the actual FIRMessaging connection that we use to receive and send messages + * while the app is in foreground. Once we have a registrationID from the FIRMessaging backend we + * are able to set up this connection which is used for any further communication with FIRMessaging + * backend. In case the connection breaks off while the app is still being used we try to rebuild + * the connection with an exponential backoff. + * + * This class also notifies the delegate about the main events happening in the lifcycle of the + * FIRMessaging connection (read FIRMessagingConnectionDelegate). All of the `on-the-wire` + * interactions with FIRMessaging are channelled through here. + */ +@interface FIRMessagingConnection : NSObject + +@property(nonatomic, readonly, assign) FIRMessagingConnectionState state; +@property(nonatomic, readonly, copy) NSString *host; +@property(nonatomic, readonly, assign) NSUInteger port; +@property(nonatomic, readwrite, weak) id delegate; + +- (instancetype)initWithAuthID:(NSString *)authId + token:(NSString *)token + host:(NSString *)host + port:(NSUInteger)port + runLoop:(NSRunLoop *)runLoop + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + fcmManager:(FIRMessagingDataMessageManager *)dataMessageManager; + +- (void)signIn; // connect +- (void)signOut; // disconnect + +/** + * Teardown the FIRMessaging connection and deallocate the resources being held up by the + * connection. + */ +- (void)teardown; + +/** + * Send proto to the wire. The message will be cached before we try to send so that in case of + * failure we can send it again later on when we have connection. + */ +- (void)sendProto:(GPBMessage *)proto; + +/** + * Send a message after the currently in progress connection succeeds, otherwise drop it. + * + * This should be used for TTL=0 messages that force a reconnect. They shouldn't be persisted + * in the RMQ, but they should be sent if the reconnect is successful. + */ +- (void)sendOnConnectOrDrop:(GPBMessage *)message; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.m new file mode 100644 index 0000000..8694326 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.m @@ -0,0 +1,708 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingConnection.h" + +#import "Protos/GtalkCore.pbobjc.h" +#import "Protos/GtalkExtensions.pbobjc.h" + +#import "FIRMessaging.h" +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingSecureSocket.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessagingVersionUtilities.h" +#import "FIRMessaging_Private.h" + +static NSInteger const kIqSelectiveAck = 12; +static NSInteger const kIqStreamAck = 13; +static int const kInvalidStreamId = -1; +// Threshold for number of messages removed that we will ack, for short lived connections +static int const kMessageRemoveAckThresholdCount = 5; + +static NSTimeInterval const kHeartbeatInterval = 30.0; +static NSTimeInterval const kConnectionTimeout = 20.0; +static int32_t const kAckingInterval = 10; + +static NSString *const kUnackedS2dIdKey = @"FIRMessagingUnackedS2dIdKey"; +static NSString *const kAckedS2dIdMapKey = @"FIRMessagingAckedS2dIdMapKey"; + +static NSString *const kRemoteFromAddress = @"from"; + +@interface FIRMessagingD2SInfo : NSObject + +@property(nonatomic, readwrite, assign) int streamId; +@property(nonatomic, readwrite, strong) NSString *d2sID; +- (instancetype)initWithStreamId:(int)streamId d2sId:(NSString *)d2sID; + +@end + +@implementation FIRMessagingD2SInfo + +- (instancetype)initWithStreamId:(int)streamId d2sId:(NSString *)d2sID { + self = [super init]; + if (self) { + _streamId = streamId; + _d2sID = [d2sID copy]; + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([object isKindOfClass:[self class]]) { + FIRMessagingD2SInfo *other = (FIRMessagingD2SInfo *)object; + return self.streamId == other.streamId && [self.d2sID isEqualToString:other.d2sID]; + } + return NO; +} + +- (NSUInteger)hash { + return [self.d2sID hash]; +} + +@end + +@interface FIRMessagingConnection () + +@property(nonatomic, readwrite, weak) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, weak) FIRMessagingDataMessageManager *dataMessageManager; + +@property(nonatomic, readwrite, assign) FIRMessagingConnectionState state; +@property(nonatomic, readwrite, copy) NSString *host; +@property(nonatomic, readwrite, assign) NSUInteger port; + +@property(nonatomic, readwrite, strong) NSString *authId; +@property(nonatomic, readwrite, strong) NSString *token; + +@property(nonatomic, readwrite, strong) FIRMessagingSecureSocket *socket; + +@property(nonatomic, readwrite, assign) int64_t lastLoginServerTimestamp; +@property(nonatomic, readwrite, assign) int lastStreamIdAcked; +@property(nonatomic, readwrite, assign) int inStreamId; +@property(nonatomic, readwrite, assign) int outStreamId; + +@property(nonatomic, readwrite, strong) NSMutableArray *unackedS2dIds; +@property(nonatomic, readwrite, strong) NSMutableDictionary *ackedS2dMap; +@property(nonatomic, readwrite, strong) NSMutableArray *d2sInfos; +// ttl=0 messages that need to be sent as soon as we establish a connection +@property(nonatomic, readwrite, strong) NSMutableArray *sendOnConnectMessages; + +@property(nonatomic, readwrite, strong) NSRunLoop *runLoop; + +@end + + +@implementation FIRMessagingConnection; + +- (instancetype)initWithAuthID:(NSString *)authId + token:(NSString *)token + host:(NSString *)host + port:(NSUInteger)port + runLoop:(NSRunLoop *)runLoop + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + fcmManager:(FIRMessagingDataMessageManager *)dataMessageManager { + self = [super init]; + if (self) { + _authId = [authId copy]; + _token = [token copy]; + _host = [host copy]; + _port = port; + _runLoop = runLoop; + _rmq2Manager = rmq2Manager; + _dataMessageManager = dataMessageManager; + + _d2sInfos = [NSMutableArray array]; + + _unackedS2dIds = [NSMutableArray arrayWithArray:[_rmq2Manager unackedS2dRmqIds]]; + _ackedS2dMap = [NSMutableDictionary dictionary]; + _sendOnConnectMessages = [NSMutableArray array]; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"host: %@, port: %lu, stream id in: %d, stream id out: %d", + self.host, + _FIRMessaging_UL(self.port), + self.inStreamId, + self.outStreamId]; +} + +- (void)signIn { + _FIRMessagingDevAssert(self.state == kFIRMessagingConnectionNotConnected, @"Invalid connection state."); + if (self.state != kFIRMessagingConnectionNotConnected) { + return; + } + + // break it up for testing + [self setupConnectionSocket]; + [self connectToSocket:self.socket]; +} + +- (void)setupConnectionSocket { + self.socket = [[FIRMessagingSecureSocket alloc] init]; + self.socket.delegate = self; +} + +- (void)connectToSocket:(FIRMessagingSecureSocket *)socket { + self.state = kFIRMessagingConnectionConnecting; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection000, + @"Start connecting to FIRMessaging service."); + [socket connectToHost:self.host port:self.port onRunLoop:self.runLoop]; +} + +- (void)signOut { + // Clear the list of messages to be sent on connect. This will only + // have messages in it if an error happened before receiving the LoginResponse. + [self.sendOnConnectMessages removeAllObjects]; + + if (self.state == kFIRMessagingConnectionSignedIn) { + [self sendClose]; + } + if (self.state != kFIRMessagingConnectionNotConnected) { + [self disconnect]; + } +} + +- (void)teardown { + if (self.state != kFIRMessagingConnectionNotConnected) { + [self disconnect]; + } +} + +#pragma mark - FIRMessagingSecureSocketDelegate + +- (void)secureSocketDidConnect:(FIRMessagingSecureSocket *)socket { + self.state = kFIRMessagingConnectionConnected; + self.lastStreamIdAcked = 0; + self.inStreamId = 0; + self.outStreamId = 0; + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection001, + @"Connected to FIRMessaging service."); + [self resetUnconfirmedAcks]; + [self sendLoginRequest:self.authId token:self.token]; +} + +- (void)didDisconnectWithSecureSocket:(FIRMessagingSecureSocket *)socket { + _FIRMessagingDevAssert(self.socket == socket, @"Invalid socket"); + _FIRMessagingDevAssert(self.socket.state == kFIRMessagingSecureSocketClosed, @"Socket already closed"); + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection002, + @"Secure socket disconnected from FIRMessaging service."); + [self disconnect]; + [self.delegate connection:self didCloseForReason:kFIRMessagingConnectionCloseReasonSocketDisconnected]; +} + +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didReceiveData:(NSData *)data + withTag:(int8_t)tag { + if (tag < 0) { + // Invalid proto tag + return; + } + + Class klassForTag = FIRMessagingGetClassForTag((FIRMessagingProtoTag)tag); + if ([klassForTag isSubclassOfClass:[NSNull class]]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeConnection003, @"Invalid tag %d for proto", + tag); + return; + } + + GPBMessage *proto = [klassForTag parseFromData:data error:NULL]; + if (tag == kFIRMessagingProtoTagLoginResponse && self.state != kFIRMessagingConnectionConnected) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection004, + @"Should not receive generated message when the connection is not connected."); + return; + } else if (tag != kFIRMessagingProtoTagLoginResponse && self.state != kFIRMessagingConnectionSignedIn) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection005, + @"Should not receive generated message when the connection is not signed in."); + return; + } + + // If traffic is received after a heartbeat it is safe to assume the connection is healthy. + [self cancelConnectionTimeoutTask]; + [self performSelector:@selector(sendHeartbeatPing) + withObject:nil + afterDelay:kHeartbeatInterval]; + + [self willProcessProto:proto]; + switch (tag) { + case kFIRMessagingProtoTagLoginResponse: + [self didReceiveLoginResponse:(GtalkLoginResponse *)proto]; + break; + case kFIRMessagingProtoTagDataMessageStanza: + [self didReceiveDataMessageStanza:(GtalkDataMessageStanza *)proto]; + break; + case kFIRMessagingProtoTagHeartbeatPing: + [self didReceiveHeartbeatPing:(GtalkHeartbeatPing *)proto]; + break; + case kFIRMessagingProtoTagHeartbeatAck: + [self didReceiveHeartbeatAck:(GtalkHeartbeatAck *)proto]; + break; + case kFIRMessagingProtoTagClose: + [self didReceiveClose:(GtalkClose *)proto]; + break; + case kFIRMessagingProtoTagIqStanza: + [self handleIqStanza:(GtalkIqStanza *)proto]; + break; + default: + [self didReceiveUnhandledProto:proto]; + break; + } +} + +// Called from secure socket once we have send the proto with given rmqId over the wire +// since we are mostly concerned with user facing messages which certainly have a rmqId +// we can retrieve them from the Rmq if necessary to look at stuff but for now we just +// log it. +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didSendProtoWithTag:(int8_t)tag + rmqId:(NSString *)rmqId { + // log the message + [self logMessage:rmqId messageType:tag isOut:YES]; +} + +#pragma mark - FIRMessagingTestConnection + +- (void)sendProto:(GPBMessage *)proto { + FIRMessagingProtoTag tag = FIRMessagingGetTagForProto(proto); + if (tag == kFIRMessagingProtoTagLoginRequest && self.state != kFIRMessagingConnectionConnected) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection006, + @"Cannot send generated message when the connection is not connected."); + return; + } else if (tag != kFIRMessagingProtoTagLoginRequest && self.state != kFIRMessagingConnectionSignedIn) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection007, + @"Cannot send generated message when the connection is not signed in."); + return; + } + + _FIRMessagingDevAssert(self.socket != nil, @"Socket shouldn't be nil"); + if (self.socket == nil) { + return; + } + + [self willSendProto:proto]; + + [self.socket sendData:proto.data withTag:tag rmqId:FIRMessagingGetRmq2Id(proto)]; +} + +- (void)sendOnConnectOrDrop:(GPBMessage *)message { + if (self.state == kFIRMessagingConnectionSignedIn) { + // If a connection has already been established, send normally + [self sendProto:message]; + } else { + // Otherwise add them to the list of messages to send after login + [self.sendOnConnectMessages addObject:message]; + } +} + ++ (GtalkLoginRequest *)loginRequestWithToken:(NSString *)token authID:(NSString *)authID { + GtalkLoginRequest *login = [[GtalkLoginRequest alloc] init]; + login.accountId = 1000000; + login.authService = GtalkLoginRequest_AuthService_AndroidId; + login.authToken = token; + login.id_p = [NSString stringWithFormat:@"%@-%@", @"ios", FIRMessagingCurrentLibraryVersion()]; + login.domain = @"mcs.android.com"; + login.deviceId = [NSString stringWithFormat:@"android-%llx", authID.longLongValue]; + login.networkType = [self currentNetworkType]; + login.resource = authID; + login.user = authID; + login.useRmq2 = YES; + login.lastRmqId = 1; // Sending not enabled yet so this stays as 1. + return login; +} + ++ (int32_t)currentNetworkType { + // http://developer.android.com/reference/android/net/ConnectivityManager.html + int32_t fcmNetworkType; + FIRMessagingNetworkStatus type = [[FIRMessaging messaging] networkType]; + switch (type) { + case kFIRMessagingReachabilityReachableViaWiFi: + fcmNetworkType = 1; + break; + + case kFIRMessagingReachabilityReachableViaWWAN: + fcmNetworkType = 0; + break; + + default: + fcmNetworkType = -1; + break; + } + return fcmNetworkType; +} + +- (void)sendLoginRequest:(NSString *)authId + token:(NSString *)token { + GtalkLoginRequest *login = [[self class] loginRequestWithToken:token authID:authId]; + + // clear the messages sent during last connection + if ([self.d2sInfos count]) { + [self.d2sInfos removeAllObjects]; + } + + if (self.unackedS2dIds.count > 0) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection008, + @"There are unacked persistent Ids in the login request: %@", + [self.unackedS2dIds.description stringByReplacingOccurrencesOfString:@"%" + withString:@"%%"]); + } + // Send out acks. + for (NSString *unackedPersistentS2dId in self.unackedS2dIds) { + [login.receivedPersistentIdArray addObject:unackedPersistentS2dId]; + } + + GtalkSetting *setting = [[GtalkSetting alloc] init]; + setting.name = @"new_vc"; + setting.value = @"1"; + [login.settingArray addObject:setting]; + + [self sendProto:login]; +} + +- (void)sendHeartbeatAck { + [self sendProto:[[GtalkHeartbeatAck alloc] init]]; +} + +- (void)sendHeartbeatPing { + // cancel the previous heartbeat request. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(sendHeartbeatPing) + object:nil]; + [self scheduleConnectionTimeoutTask]; + [self sendProto:[[GtalkHeartbeatPing alloc] init]]; +} + ++ (GtalkIqStanza *)createStreamAck { + GtalkIqStanza *iq = [[GtalkIqStanza alloc] init]; + iq.type = GtalkIqStanza_IqType_Set; + iq.id_p = @""; + GtalkExtension *ext = [[GtalkExtension alloc] init]; + ext.id_p = kIqStreamAck; + ext.data_p = @""; + iq.extension = ext; + return iq; +} + +- (void)sendStreamAck { + GtalkIqStanza *iq = [[self class] createStreamAck]; + [self sendProto:iq]; +} + +- (void)sendClose { + [self sendProto:[[GtalkClose alloc] init]]; +} + +- (void)handleIqStanza:(GtalkIqStanza *)iq { + if (iq.hasExtension) { + if (iq.extension.id_p == kIqStreamAck) { + [self didReceiveStreamAck:iq]; + return; + } + if (iq.extension.id_p == kIqSelectiveAck) { + [self didReceiveSelectiveAck:iq]; + return; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection009, @"Unknown ack extension id %d.", + iq.extension.id_p); + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection010, @"Ip stanza without extension."); + } + [self didReceiveUnhandledProto:iq]; +} + +- (void)didReceiveLoginResponse:(GtalkLoginResponse *)loginResponse { + if (loginResponse.hasError) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection011, + @"Login error with type: %@, message: %@.", loginResponse.error.type, + loginResponse.error.message); + return; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection012, @"Logged onto MCS service."); + // We sent the persisted list of unack'd messages with login so we can assume they have been ack'd + // by the server. + _FIRMessagingDevAssert(self.unackedS2dIds.count == 0, @"No ids present"); + _FIRMessagingDevAssert(self.outStreamId == 1, @"Login should be the first stream id"); + + self.state = kFIRMessagingConnectionSignedIn; + self.lastLoginServerTimestamp = loginResponse.serverTimestamp; + [self.delegate didLoginWithConnection:self]; + [self sendHeartbeatPing]; + + // Add all the TTL=0 messages on connect + for (GPBMessage *message in self.sendOnConnectMessages) { + [self sendProto:message]; + } + [self.sendOnConnectMessages removeAllObjects]; +} + +- (void)didReceiveHeartbeatPing:(GtalkHeartbeatPing *)heartbeatPing { + [self sendHeartbeatAck]; +} + +- (void)didReceiveHeartbeatAck:(GtalkHeartbeatAck *)heartbeatAck { +} + +- (void)didReceiveDataMessageStanza:(GtalkDataMessageStanza *)dataMessageStanza { + // TODO: Maybe add support raw data later + [self.delegate connectionDidRecieveMessage:dataMessageStanza]; +} + +- (void)didReceiveUnhandledProto:(GPBMessage *)proto { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection013, @"Received unhandled proto"); +} + +- (void)didReceiveStreamAck:(GtalkIqStanza *)iq { + // Server received some stuff from us we don't really need to do anything special +} + +- (void)didReceiveSelectiveAck:(GtalkIqStanza *)iq { + GtalkExtension *extension = iq.extension; + if (extension) { + int extensionId = extension.id_p; + if (extensionId == kIqSelectiveAck) { + + NSString *dataString = extension.data_p; + GtalkSelectiveAck *selectiveAck = [[GtalkSelectiveAck alloc] init]; + [selectiveAck mergeFromData:[dataString dataUsingEncoding:NSUTF8StringEncoding] + extensionRegistry:nil]; + + NSArray *acks = [selectiveAck idArray]; + + // we've received ACK's + [self.delegate connectionDidReceiveAckForRmqIds:acks]; + + // resend unacked messages + [self.dataMessageManager resendMessagesWithConnection:self]; + } + } +} + +- (void)didReceiveClose:(GtalkClose *)close { + [self disconnect]; +} + +- (void)willProcessProto:(GPBMessage *)proto { + self.inStreamId++; + + if ([proto isKindOfClass:GtalkDataMessageStanza.class]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection014, + @"RMQ: Receiving %@ with rmq_id: %@ incoming stream Id: %d", + proto.class, FIRMessagingGetRmq2Id(proto), self.inStreamId); + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection015, + @"RMQ: Receiving %@ with incoming stream Id: %d.", proto.class, + self.inStreamId); + } + int streamId = FIRMessagingGetLastStreamId(proto); + if (streamId != kInvalidStreamId) { + // confirm the D2S messages that were sent by us + [self confirmAckedD2sIdsWithStreamId:streamId]; + + // We can now confirm that our ack was received by the server and start our unack'd list fresh + // with the proto we just received. + [self confirmAckedS2dIdsWithStreamId:streamId]; + } + NSString *rmq2Id = FIRMessagingGetRmq2Id(proto); + if (rmq2Id != nil) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection016, + @"RMQ: Add unacked persistent Id: %@.", + [rmq2Id stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]); + [self.unackedS2dIds addObject:rmq2Id]; + [self.rmq2Manager saveS2dMessageWithRmqId:rmq2Id]; // RMQ save + } + BOOL explicitAck = ([proto isKindOfClass:[GtalkDataMessageStanza class]] && + [(GtalkDataMessageStanza *)proto immediateAck]); + // If we have not sent anything and the ack threshold has been reached then explicitly send one + // to notify the server that we have received messages. + if (self.inStreamId - self.lastStreamIdAcked >= kAckingInterval || explicitAck) { + [self sendStreamAck]; + } +} + +- (void)willSendProto:(GPBMessage *)proto { + self.outStreamId++; + + NSString *rmq2Id = FIRMessagingGetRmq2Id(proto); + if ([rmq2Id length]) { + FIRMessagingD2SInfo *d2sInfo = [[FIRMessagingD2SInfo alloc] initWithStreamId:self.outStreamId d2sId:rmq2Id]; + [self.d2sInfos addObject:d2sInfo]; + } + + // each time we send a d2s message, it acks previously received + // s2d messages via the last (s2d) stream id received. + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection017, + @"RMQ: Sending %@ with outgoing stream Id: %d.", proto.class, + self.outStreamId); + // We have received messages since last time we sent something - send ack info to server. + if (self.inStreamId > self.lastStreamIdAcked) { + FIRMessagingSetLastStreamId(proto, self.inStreamId); + self.lastStreamIdAcked = self.inStreamId; + } + + if (self.unackedS2dIds.count > 0) { + // Move all 'unack'd' messages to the ack'd map so they can be removed once the + // ack is confirmed. + NSArray *ackedS2dIds = [NSArray arrayWithArray:self.unackedS2dIds]; + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection018, @"RMQ: Mark persistent Ids as acked: %@.", + [ackedS2dIds.description stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]); + [self.unackedS2dIds removeAllObjects]; + self.ackedS2dMap[[@(self.outStreamId) stringValue]] = ackedS2dIds; + } +} + +#pragma mark - Private + +/** + * This processes the s2d message received in reference to the d2s messages + * that we have sent before. + */ +- (void)confirmAckedD2sIdsWithStreamId:(int)lastReceivedStreamId { + NSMutableArray *d2sIdsAcked = [NSMutableArray array]; + for (FIRMessagingD2SInfo *d2sInfo in self.d2sInfos) { + if (lastReceivedStreamId < d2sInfo.streamId) { + break; + } + [d2sIdsAcked addObject:d2sInfo]; + } + + NSMutableArray *rmqIds = [NSMutableArray arrayWithCapacity:[d2sIdsAcked count]]; + // remove ACK'ed messages + for (FIRMessagingD2SInfo *d2sInfo in d2sIdsAcked) { + if ([d2sInfo.d2sID length]) { + [rmqIds addObject:d2sInfo.d2sID]; + } + [self.d2sInfos removeObject:d2sInfo]; + } + [self.delegate connectionDidReceiveAckForRmqIds:rmqIds]; + int count = [self.delegate connectionDidReceiveAckForRmqIds:rmqIds]; + if (kMessageRemoveAckThresholdCount > 0 && count >= kMessageRemoveAckThresholdCount) { + // For short lived connections, if a large number of messages are removed, send an + // ack straight away so the server knows that this message was received. + [self sendStreamAck]; + } +} + +/** + * Called when a stream ACK or a selective ACK are received - this indicates the message has + * been received by MCS. + */ +- (void)didReceiveAckForRmqIds:(NSArray *)rmqIds { + // TODO: let the user know that the following messages were received by the server +} + +- (void)confirmAckedS2dIdsWithStreamId:(int)lastReceivedStreamId { + // If the server hasn't received the streamId yet. + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection019, + @"RMQ: Server last received stream Id: %d.", lastReceivedStreamId); + if (lastReceivedStreamId < self.outStreamId) { + // TODO: This could be a good indicator that we need to re-send something (acks)? + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection020, + @"RMQ: There are unsent messages that should be send...\n" + "server received: %d\nlast stream id sent: %d", + lastReceivedStreamId, self.outStreamId); + } + + NSSet *ackedStreamIds = + [self.ackedS2dMap keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) { + NSString *streamId = key; + return streamId.intValue <= lastReceivedStreamId; + }]; + NSMutableArray *s2dIdsToDelete = [NSMutableArray array]; + + for (NSString *streamId in ackedStreamIds) { + NSArray *ackedS2dIds = self.ackedS2dMap[streamId]; + if (ackedS2dIds.count > 0) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection021, + @"RMQ: Mark persistent Ids as confirmed by stream id %@: %@.", streamId, + [ackedS2dIds.description stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]); + [self.ackedS2dMap removeObjectForKey:streamId]; + } + + [s2dIdsToDelete addObjectsFromArray:ackedS2dIds]; + } + + // clean up s2d ids that the server knows we've received. + // we let the server know via a s2d last stream id received in a + // d2s message. the server lets us know it has received our d2s + // message via a d2s last stream id received in a s2d message. + [self.rmq2Manager removeS2dIds:s2dIdsToDelete]; +} + +- (void)resetUnconfirmedAcks { + [self.ackedS2dMap enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [self.unackedS2dIds addObjectsFromArray:obj]; + }]; + [self.ackedS2dMap removeAllObjects]; +} + +- (void)disconnect { + _FIRMessagingDevAssert(self.state != kFIRMessagingConnectionNotConnected, @"Connection already not connected"); + // cancel pending timeout tasks. + [self cancelConnectionTimeoutTask]; + // cancel pending heartbeat. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(sendHeartbeatPing) + object:nil]; + // Unset the delegate. FIRMessagingConnection will not receive further events from the socket from now on. + self.socket.delegate = nil; + [self.socket disconnect]; + self.state = kFIRMessagingConnectionNotConnected; +} + +- (void)connectionTimedOut { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection022, + @"Connection to FIRMessaging service timed out."); + [self disconnect]; + [self.delegate connection:self didCloseForReason:kFIRMessagingConnectionCloseReasonTimeout]; +} + +- (void)scheduleConnectionTimeoutTask { + // cancel the previous heartbeat timeout event and schedule a new one. + [self cancelConnectionTimeoutTask]; + [self performSelector:@selector(connectionTimedOut) + withObject:nil + afterDelay:[self connectionTimeoutInterval]]; +} + +- (void)cancelConnectionTimeoutTask { + // cancel pending timeout tasks. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(connectionTimedOut) + object:nil]; +} + +- (void)logMessage:(NSString *)description messageType:(int)messageType isOut:(BOOL)isOut { + messageType = isOut ? -messageType : messageType; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection023, + @"Send msg: %@ type: %d inStreamId: %d outStreamId: %d", description, + messageType, self.inStreamId, self.outStreamId); +} + +- (NSTimeInterval)connectionTimeoutInterval { + return kConnectionTimeout; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.h new file mode 100644 index 0000000..9a3ce04 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Global constants to be put here. + * + */ +#import + +#ifndef _FIRMessaging_CONSTANTS_H +#define _FIRMessaging_CONSTANTS_H + +FOUNDATION_EXPORT NSString *const kFIRMessagingRawDataKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingCollapseKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingFromKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingSendTo; +FOUNDATION_EXPORT NSString *const kFIRMessagingSendTTL; +FOUNDATION_EXPORT NSString *const kFIRMessagingSendDelay; +FOUNDATION_EXPORT NSString *const kFIRMessagingSendMessageID; +FOUNDATION_EXPORT NSString *const KFIRMessagingSendMessageAppData; + +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageInternalReservedKeyword; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessagePersistentIDKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageIDKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageAPNSContentAvailableKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageSyncViaMCSKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageSyncMessageTTLKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageLinkKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingRemoteNotificationsProxyEnabledInfoPlistKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingSubDirectoryName; + +// Notifications +FOUNDATION_EXPORT NSString *const kFIRMessagingCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRMessagingAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRMessagingFCMTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRMessagingInstanceIDTokenRefreshNotification __deprecated_msg("Use kFIRMessagingRegistrationTokenRefreshNotification instead"); +FOUNDATION_EXPORT NSString *const kFIRMessagingRegistrationTokenRefreshNotification; + +FOUNDATION_EXPORT const int kFIRMessagingSendTtlDefault; // 24 hours + +#endif diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.m new file mode 100644 index 0000000..e50c923 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.m @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingConstants.h" + +NSString *const kFIRMessagingRawDataKey = @"rawData"; +NSString *const kFIRMessagingCollapseKey = @"collapse_key"; +NSString *const kFIRMessagingFromKey = @"from"; + +NSString *const kFIRMessagingSendTo = @"google." @"to"; +NSString *const kFIRMessagingSendTTL = @"google." @"ttl"; +NSString *const kFIRMessagingSendDelay = @"google." @"delay"; +NSString *const kFIRMessagingSendMessageID = @"google." @"msg_id"; +NSString *const KFIRMessagingSendMessageAppData = @"google." @"data"; + +NSString *const kFIRMessagingMessageInternalReservedKeyword = @"gcm."; +NSString *const kFIRMessagingMessagePersistentIDKey = @"persistent_id"; + +NSString *const kFIRMessagingMessageIDKey = @"gcm." @"message_id"; +NSString *const kFIRMessagingMessageAPNSContentAvailableKey = @"content-available"; +NSString *const kFIRMessagingMessageSyncViaMCSKey = @"gcm." @"duplex"; +NSString *const kFIRMessagingMessageSyncMessageTTLKey = @"gcm." @"ttl"; +NSString *const kFIRMessagingMessageLinkKey = @"gcm." @"app_link"; + +NSString *const kFIRMessagingRemoteNotificationsProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +NSString *const kFIRMessagingSubDirectoryName = @"Google/FirebaseMessaging"; + +// Notifications +NSString *const kFIRMessagingCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRMessagingAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRMessagingFCMTokenNotification = @"com.firebase.iid.notif.fcm-token"; +NSString *const kFIRMessagingInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +NSString *const kFIRMessagingRegistrationTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; + +const int kFIRMessagingSendTtlDefault = 24 * 60 * 60; // 24 hours diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.h new file mode 100644 index 0000000..83e6444 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerCategory; +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerLocalTimeStart; +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerLocalTimeEnd; +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerBodyKey; + +@interface FIRMessagingContextManagerService : NSObject + +/** + * Check if the message is a context manager message or not. + * + * @param message The message to verify. + * + * @return YES if the message is a context manager message else NO. + */ ++ (BOOL)isContextManagerMessage:(NSDictionary *)message; + +/** + * Handle context manager message. + * + * @param message The message to handle. + * + * @return YES if the message was handled successfully else NO. + */ ++ (BOOL)handleContextManagerMessage:(NSDictionary *)message; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.m new file mode 100644 index 0000000..d177014 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.m @@ -0,0 +1,205 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingContextManagerService.h" + +#import + +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" + +#define kFIRMessagingContextManagerPrefixKey @"google.c.cm." +#define kFIRMessagingContextManagerNotificationKeyPrefix @"gcm.notification." + +static NSString *const kLogTag = @"FIRMessagingAnalytics"; + +static NSString *const kLocalTimeFormatString = @"yyyy-MM-dd HH:mm:ss"; + +static NSString *const kContextManagerPrefixKey = kFIRMessagingContextManagerPrefixKey; + +// Local timed messages (format yyyy-mm-dd HH:mm:ss) +NSString *const kFIRMessagingContextManagerLocalTimeStart = kFIRMessagingContextManagerPrefixKey @"lt_start"; +NSString *const kFIRMessagingContextManagerLocalTimeEnd = kFIRMessagingContextManagerPrefixKey @"lt_end"; + +// Local Notification Params +NSString *const kFIRMessagingContextManagerBodyKey = kFIRMessagingContextManagerNotificationKeyPrefix @"body"; +NSString *const kFIRMessagingContextManagerTitleKey = kFIRMessagingContextManagerNotificationKeyPrefix @"title"; +NSString *const kFIRMessagingContextManagerBadgeKey = kFIRMessagingContextManagerNotificationKeyPrefix @"badge"; +NSString *const kFIRMessagingContextManagerCategoryKey = + kFIRMessagingContextManagerNotificationKeyPrefix @"click_action"; +NSString *const kFIRMessagingContextManagerSoundKey = kFIRMessagingContextManagerNotificationKeyPrefix @"sound"; +NSString *const kFIRMessagingContextManagerContentAvailableKey = + kFIRMessagingContextManagerNotificationKeyPrefix @"content-available"; + +typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) { + FIRMessagingContextManagerMessageTypeNone, + FIRMessagingContextManagerMessageTypeLocalTime, +}; + +@implementation FIRMessagingContextManagerService + ++ (BOOL)isContextManagerMessage:(NSDictionary *)message { + // For now we only support local time in ContextManager. + if (![message[kFIRMessagingContextManagerLocalTimeStart] length]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeContextManagerService000, + @"Received message missing local start time, dropped."); + return NO; + } + + return YES; +} + ++ (BOOL)handleContextManagerMessage:(NSDictionary *)message { + NSString *startTimeString = message[kFIRMessagingContextManagerLocalTimeStart]; + if (startTimeString.length) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeContextManagerService001, + @"%@ Received context manager message with local time %@", kLogTag, + startTimeString); + return [self handleContextManagerLocalTimeMessage:message]; + } + + return NO; +} + ++ (BOOL)handleContextManagerLocalTimeMessage:(NSDictionary *)message { + NSString *startTimeString = message[kFIRMessagingContextManagerLocalTimeStart]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setDateFormat:kLocalTimeFormatString]; + NSDate *startDate = [dateFormatter dateFromString:startTimeString]; + + _FIRMessagingDevAssert(startDate, @"Invalid local start date format %@", startTimeString); + if (!startTimeString) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService002, + @"Invalid local start date format %@. Message dropped", + startTimeString); + return NO; + } + + NSDate *currentDate = [NSDate date]; + + if ([currentDate compare:startDate] == NSOrderedAscending) { + [self scheduleLocalNotificationForMessage:message + atDate:startDate]; + } else { + // check end time has not passed + NSString *endTimeString = message[kFIRMessagingContextManagerLocalTimeEnd]; + if (!endTimeString) { + FIRMessagingLoggerInfo( + kFIRMessagingMessageCodeContextManagerService003, + @"No end date specified for message, start date elapsed. Message dropped."); + return YES; + } + + NSDate *endDate = [dateFormatter dateFromString:endTimeString]; + + _FIRMessagingDevAssert(endDate, @"Invalid local end date format %@", endTimeString); + if (!endTimeString) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService004, + @"Invalid local end date format %@. Message dropped", endTimeString); + return NO; + } + + if ([endDate compare:currentDate] == NSOrderedAscending) { + // end date has already passed drop the message + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeContextManagerService005, + @"End date %@ has already passed. Message dropped.", endTimeString); + return YES; + } + + // schedule message right now (buffer 10s) + [self scheduleLocalNotificationForMessage:message + atDate:[currentDate dateByAddingTimeInterval:10]]; + } + return YES; +} + ++ (void)scheduleLocalNotificationForMessage:(NSDictionary *)message + atDate:(NSDate *)date { +#if TARGET_OS_IOS + NSDictionary *apsDictionary = message; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + UILocalNotification *notification = [[UILocalNotification alloc] init]; +#pragma clang diagnostic pop + + // A great way to understand timezones and UILocalNotifications + // http://stackoverflow.com/questions/18424569/understanding-uilocalnotification-timezone + notification.timeZone = [NSTimeZone defaultTimeZone]; + notification.fireDate = date; + + // In the current solution all of the display stuff goes into a special "aps" dictionary + // being sent in the message. + if ([apsDictionary[kFIRMessagingContextManagerBodyKey] length]) { + notification.alertBody = apsDictionary[kFIRMessagingContextManagerBodyKey]; + } + if ([apsDictionary[kFIRMessagingContextManagerTitleKey] length]) { + // |alertTitle| is iOS 8.2+, so check if we can set it + if ([notification respondsToSelector:@selector(setAlertTitle:)]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + notification.alertTitle = apsDictionary[kFIRMessagingContextManagerTitleKey]; +#pragma pop + } + } + + if (apsDictionary[kFIRMessagingContextManagerSoundKey]) { + notification.soundName = apsDictionary[kFIRMessagingContextManagerSoundKey]; + } + if (apsDictionary[kFIRMessagingContextManagerBadgeKey]) { + notification.applicationIconBadgeNumber = + [apsDictionary[kFIRMessagingContextManagerBadgeKey] integerValue]; + } + if (apsDictionary[kFIRMessagingContextManagerCategoryKey]) { + // |category| is iOS 8.0+, so check if we can set it + if ([notification respondsToSelector:@selector(setCategory:)]) { + notification.category = apsDictionary[kFIRMessagingContextManagerCategoryKey]; + } + } + + NSDictionary *userInfo = [self parseDataFromMessage:message]; + if (userInfo.count) { + notification.userInfo = userInfo; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + UIApplication *application = FIRMessagingUIApplication(); + if (!application) { + return; + } + [application scheduleLocalNotification:notification]; +#pragma clang diagnostic pop +#endif +} + ++ (NSDictionary *)parseDataFromMessage:(NSDictionary *)message { + NSMutableDictionary *data = [NSMutableDictionary dictionary]; + for (NSObject *key in message) { + if ([key isKindOfClass:[NSString class]]) { + NSString *keyString = (NSString *)key; + if ([keyString isEqualToString:kFIRMessagingContextManagerContentAvailableKey]) { + continue; + } else if ([keyString hasPrefix:kContextManagerPrefixKey]) { + continue; + } + } + data[[key copy]] = message[key]; + } + return [data copy]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.h new file mode 100644 index 0000000..cf8df74 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.h @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GtalkDataMessageStanza; + +@class FIRMessagingClient; +@class FIRMessagingConnection; +@class FIRMessagingReceiver; +@class FIRMessagingRmqManager; +@class FIRMessagingSyncMessageManager; + +@protocol FIRMessagingDataMessageManagerDelegate + +#pragma mark - Downstream Callbacks + +/** + * Invoked when FIRMessaging receives a downstream message via the MCS connection. + * Let's the user know that they have received a new message by invoking the + * App's remoteNotification callback. + * + * @param message The downstream message received by the MCS connection. + */ +- (void)didReceiveMessage:(nonnull NSDictionary *)message + withIdentifier:(nullable NSString *)messageID; + +#pragma mark - Upstream Callbacks + +/** + * Notify the app that FIRMessaging will soon be sending the upstream message requested by the app. + * + * @param messageID The messageId passed in by the app to track this particular message. + * @param error The error in case FIRMessaging cannot send the message upstream. + */ +- (void)willSendDataMessageWithID:(nullable NSString *)messageID error:(nullable NSError *)error; + +/** + * Notify the app that FIRMessaging did successfully send it's message via the MCS + * connection and the message was successfully delivered. + * + * @param messageId The messageId passed in by the app to track this particular + * message. + */ +- (void)didSendDataMessageWithID:(nonnull NSString *)messageId; + +#pragma mark - Server Callbacks + +/** + * Notify the app that FIRMessaging server deleted some messages which exceeded storage limits. This + * indicates the "deleted_messages" message type we received from the server. + */ +- (void)didDeleteMessagesOnServer; + +@end + +/** + * This manages all of the data messages being sent by the client and also the messages that + * were received from the server. + */ +@interface FIRMessagingDataMessageManager : NSObject + +NS_ASSUME_NONNULL_BEGIN + +- (instancetype)initWithDelegate:(id)delegate + client:(FIRMessagingClient *)client + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + syncMessageManager:(FIRMessagingSyncMessageManager *)syncMessageManager; + +- (void)setDeviceAuthID:(NSString *)deviceAuthID secretToken:(NSString *)secretToken; + +- (void)refreshDelayedMessages; + +#pragma mark - Receive + +- (nullable NSDictionary *)processPacket:(GtalkDataMessageStanza *)packet; +- (void)didReceiveParsedMessage:(NSDictionary *)message; + +#pragma mark - Send + +- (void)sendDataMessageStanza:(NSMutableDictionary *)dataMessage; +- (void)didSendDataMessageStanza:(GtalkDataMessageStanza *)message; + +- (void)resendMessagesWithConnection:(FIRMessagingConnection *)connection; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.m new file mode 100644 index 0000000..b62763a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.m @@ -0,0 +1,528 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingDataMessageManager.h" + +#import "Protos/GtalkCore.pbobjc.h" + +#import "FIRMessagingClient.h" +#import "FIRMessagingConnection.h" +#import "FIRMessagingConstants.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingDelayedMessageQueue.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingReceiver.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessaging_Private.h" +#import "FIRMessagingSyncMessageManager.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +static const int kMaxAppDataSizeDefault = 4 * 1024; // 4k +static const int kMinDelaySeconds = 1; // 1 second +static const int kMaxDelaySeconds = 60 * 60; // 1 hour + +static NSString *const kFromForFIRMessagingMessages = @"mcs.android.com"; +static NSString *const kGSFMessageCategory = @"com.google.android.gsf.gtalkservice"; +// TODO: Update Gcm to FIRMessaging in the constants below +static NSString *const kFCMMessageCategory = @"com.google.gcm"; +static NSString *const kMessageReservedPrefix = @"google."; + +static NSString *const kFCMMessageSpecialMessage = @"message_type"; + +// special messages sent by the server +static NSString *const kFCMMessageTypeDeletedMessages = @"deleted_messages"; + +static NSString *const kMCSNotificationPrefix = @"gcm.notification."; +static NSString *const kDataMessageNotificationKey = @"notification"; + + +typedef NS_ENUM(int8_t, UpstreamForceReconnect) { + // Never force reconnect on upstream messages + kUpstreamForceReconnectOff = 0, + // Force reconnect for TTL=0 upstream messages + kUpstreamForceReconnectTTL0 = 1, + // Force reconnect for all upstream messages + kUpstreamForceReconnectAll = 2, +}; + +@interface FIRMessagingDataMessageManager () + +@property(nonatomic, readwrite, weak) FIRMessagingClient *client; +@property(nonatomic, readwrite, weak) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, weak) FIRMessagingSyncMessageManager *syncMessageManager; +@property(nonatomic, readwrite, weak) id delegate; +@property(nonatomic, readwrite, strong) FIRMessagingDelayedMessageQueue *delayedMessagesQueue; + +@property(nonatomic, readwrite, assign) int ttl; +@property(nonatomic, readwrite, copy) NSString *deviceAuthID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, assign) int maxAppDataSize; +@property(nonatomic, readwrite, assign) UpstreamForceReconnect upstreamForceReconnect; + +@end + +@implementation FIRMessagingDataMessageManager + +- (instancetype)initWithDelegate:(id)delegate + client:(FIRMessagingClient *)client + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + syncMessageManager:(FIRMessagingSyncMessageManager *)syncMessageManager { + self = [super init]; + if (self) { + _delegate = delegate; + _client = client; + _rmq2Manager = rmq2Manager; + _syncMessageManager = syncMessageManager; + _ttl = kFIRMessagingSendTtlDefault; + _maxAppDataSize = kMaxAppDataSizeDefault; + // on by default + _upstreamForceReconnect = kUpstreamForceReconnectAll; + } + return self; +} + +- (void)setDeviceAuthID:(NSString *)deviceAuthID secretToken:(NSString *)secretToken { + _FIRMessagingDevAssert([deviceAuthID length] && [secretToken length], + @"Invalid credentials for FIRMessaging"); + self.deviceAuthID = deviceAuthID; + self.secretToken = secretToken; +} + +- (void)refreshDelayedMessages { + FIRMessaging_WEAKIFY(self); + self.delayedMessagesQueue = + [[FIRMessagingDelayedMessageQueue alloc] initWithRmqScanner:self.rmq2Manager + sendDelayedMessagesHandler:^(NSArray *messages) { + FIRMessaging_STRONGIFY(self); + [self sendDelayedMessages:messages]; + }]; +} + +- (nullable NSDictionary *)processPacket:(GtalkDataMessageStanza *)dataMessage { + NSString *category = dataMessage.category; + NSString *from = dataMessage.from; + if ([kFCMMessageCategory isEqualToString:category] || + [kGSFMessageCategory isEqualToString:category]) { + [self handleMCSDataMessage:dataMessage]; + return nil; + } else if ([kFromForFIRMessagingMessages isEqualToString:from]) { + [self handleMCSDataMessage:dataMessage]; + return nil; + } + + return [self parseDataMessage:dataMessage]; +} + +- (void)handleMCSDataMessage:(GtalkDataMessageStanza *)dataMessage { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager000, + @"Received message for FIRMessaging from downstream %@", dataMessage); +} + +- (NSDictionary *)parseDataMessage:(GtalkDataMessageStanza *)dataMessage { + NSMutableDictionary *message = [NSMutableDictionary dictionary]; + NSString *from = [dataMessage from]; + if ([from length]) { + message[kFIRMessagingFromKey] = from; + } + + // raw data + NSData *rawData = [dataMessage rawData]; + if ([rawData length]) { + message[kFIRMessagingRawDataKey] = rawData; + } + + NSString *token = [dataMessage token]; + if ([token length]) { + message[kFIRMessagingCollapseKey] = token; + } + + // Add the persistent_id. This would be removed later before sending the message to the device. + NSString *persistentID = [dataMessage persistentId]; + _FIRMessagingDevAssert([persistentID length], @"Invalid MCS message without persistentID"); + if ([persistentID length]) { + message[kFIRMessagingMessageIDKey] = persistentID; + } + + // third-party data + for (GtalkAppData *item in dataMessage.appDataArray) { + _FIRMessagingDevAssert(item.hasKey && item.hasValue, @"Invalid AppData"); + + // do not process the "from" key -- is not useful + if ([kFIRMessagingFromKey isEqualToString:item.key]) { + continue; + } + + // Filter the "gcm.notification." keys in the message + if ([item.key hasPrefix:kMCSNotificationPrefix]) { + NSString *key = [item.key substringFromIndex:[kMCSNotificationPrefix length]]; + if ([key length]) { + if (!message[kDataMessageNotificationKey]) { + message[kDataMessageNotificationKey] = [NSMutableDictionary dictionary]; + } + message[kDataMessageNotificationKey][key] = item.value; + } else { + _FIRMessagingDevAssert([key length], @"Invalid key in MCS message: %@", key); + FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager001, + @"Invalid key in MCS message: %@", key); + } + continue; + } + + // Filter the "gcm.duplex" key + if ([item.key isEqualToString:kFIRMessagingMessageSyncViaMCSKey]) { + BOOL value = [item.value boolValue]; + message[kFIRMessagingMessageSyncViaMCSKey] = @(value); + continue; + } + + // do not allow keys with "reserved" keyword + if ([[item.key lowercaseString] hasPrefix:kMessageReservedPrefix]) { + continue; + } + + [message setObject:item.value forKey:item.key]; + } + // TODO: Add support for encrypting raw data later + return [NSDictionary dictionaryWithDictionary:message]; +} + +- (void)didReceiveParsedMessage:(NSDictionary *)message { + if ([message[kFCMMessageSpecialMessage] length]) { + NSString *messageType = message[kFCMMessageSpecialMessage]; + if ([kFCMMessageTypeDeletedMessages isEqualToString:messageType]) { + // TODO: Maybe trim down message to remove some unnecessary fields. + // tell the FCM receiver of deleted messages + [self.delegate didDeleteMessagesOnServer]; + return; + } + FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager002, + @"Invalid message type received: %@", messageType); + } else if (message[kFIRMessagingMessageSyncViaMCSKey]) { + // Update SYNC_RMQ with the message + BOOL isDuplicate = [self.syncMessageManager didReceiveMCSSyncMessage:message]; + if (isDuplicate) { + return; + } + } + NSString *messageId = message[kFIRMessagingMessageIDKey]; + NSDictionary *filteredMessage = [self filterInternalFIRMessagingKeysFromMessage:message]; + [self.delegate didReceiveMessage:filteredMessage withIdentifier:messageId]; +} + +- (NSDictionary *)filterInternalFIRMessagingKeysFromMessage:(NSDictionary *)message { + NSMutableDictionary *newMessage = [NSMutableDictionary dictionaryWithDictionary:message]; + for (NSString *key in message) { + if ([key hasPrefix:kFIRMessagingMessageInternalReservedKeyword]) { + [newMessage removeObjectForKey:key]; + } + } + return [newMessage copy]; +} + +- (void)sendDataMessageStanza:(NSMutableDictionary *)dataMessage { + NSNumber *ttlNumber = dataMessage[kFIRMessagingSendTTL]; + NSString *to = dataMessage[kFIRMessagingSendTo]; + NSString *msgId = dataMessage[kFIRMessagingSendMessageID]; + NSString *appPackage = [self categoryForUpstreamMessages]; + GtalkDataMessageStanza *stanza = [[GtalkDataMessageStanza alloc] init]; + + // TODO: enforce TTL (right now only ttl=0 is special, means no storage) + int ttl = [ttlNumber intValue]; + if (ttl < 0 || ttl > self.ttl) { + ttl = self.ttl; + } + [stanza setTtl:ttl]; + [stanza setSent:FIRMessagingCurrentTimestampInSeconds()]; + + int delay = [self delayForMessage:dataMessage]; + if (delay > 0) { + [stanza setMaxDelay:delay]; + } + + if (msgId) { + [stanza setId_p:msgId]; + } + + // collapse key as given by the sender + NSString *token = dataMessage[KFIRMessagingSendMessageAppData][kFIRMessagingCollapseKey]; + if ([token length]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager003, + @"FIRMessaging using %@ as collapse key", token); + [stanza setToken:token]; + } + + if (!self.secretToken) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager004, + @"Trying to send data message without a secret token. " + @"Authentication failed."); + [self willSendDataMessageFail:stanza + withMessageId:msgId + error:kFIRMessagingErrorCodeMissingDeviceID]; + return; + } + + if (![to length]) { + [self willSendDataMessageFail:stanza withMessageId:msgId error:kFIRMessagingErrorMissingTo]; + return; + } + [stanza setTo:to]; + [stanza setCategory:appPackage]; + // required field in the proto this is set by the server + // set it to a sentinel so the runtime doesn't throw an exception + [stanza setFrom:@""]; + + // MCS itself would set the registration ID + // [stanza setRegId:nil]; + + int size = [self addData:dataMessage[KFIRMessagingSendMessageAppData] toStanza:stanza]; + if (size > kMaxAppDataSizeDefault) { + [self willSendDataMessageFail:stanza withMessageId:msgId error:kFIRMessagingErrorSizeExceeded]; + return; + } + + BOOL useRmq = (ttl != 0) && (msgId != nil); + if (useRmq) { + if (!self.client.isConnected) { + // do nothing assuming rmq save is enabled + } + + NSError *error; + if (![self.rmq2Manager saveRmqMessage:stanza error:&error]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager005, @"%@", error); + [self willSendDataMessageFail:stanza withMessageId:msgId error:kFIRMessagingErrorSave]; + return; + } + + [self willSendDataMessageSuccess:stanza withMessageId:msgId]; + } + + // if delay > 0 we don't really care about sending the message right now + // so we piggy-back on any other urgent(delay = 0) message that we are sending + if (delay > 0 && [self delayMessage:stanza]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager006, @"Delaying Message %@", + dataMessage); + return; + } + // send delayed messages + [self sendDelayedMessages:[self.delayedMessagesQueue removeDelayedMessages]]; + + BOOL sending = [self tryToSendDataMessageStanza:stanza]; + if (!sending) { + if (useRmq) { + NSString *event __unused = [NSString stringWithFormat:@"Queued message: %@", [stanza id_p]]; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager007, @"%@", event); + } else { + [self willSendDataMessageFail:stanza + withMessageId:msgId + error:kFIRMessagingErrorCodeNetwork]; + return; + } + } +} + +- (void)sendDelayedMessages:(NSArray *)delayedMessages { + for (GtalkDataMessageStanza *message in delayedMessages) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager008, + @"%@ Sending delayed message %@", @"DMM", message); + [message setActualDelay:(int)(FIRMessagingCurrentTimestampInSeconds() - message.sent)]; + [self tryToSendDataMessageStanza:message]; + } +} + +- (void)didSendDataMessageStanza:(GtalkDataMessageStanza *)message { + NSString *msgId = [message id_p] ?: @""; + [self.delegate didSendDataMessageWithID:msgId]; +} + +- (void)addParamWithKey:(NSString *)key + value:(NSString *)val + toStanza:(GtalkDataMessageStanza *)stanza { + if (!key || !val) { + return; + } + GtalkAppData *appData = [[GtalkAppData alloc] init]; + [appData setKey:key]; + [appData setValue:val]; + [[stanza appDataArray] addObject:appData]; +} + +/** + @return The size of the data being added to stanza. + */ +- (int)addData:(NSDictionary *)data toStanza:(GtalkDataMessageStanza *)stanza { + int size = 0; + for (NSString *key in data) { + NSObject *val = data[key]; + if ([val isKindOfClass:[NSString class]]) { + NSString *strVal = (NSString *)val; + [self addParamWithKey:key value:strVal toStanza:stanza]; + size += [key length] + [strVal length]; + } else if ([val isKindOfClass:[NSNumber class]]) { + NSString *strVal = [(NSNumber *)val stringValue]; + [self addParamWithKey:key value:strVal toStanza:stanza]; + size += [key length] + [strVal length]; + } else if ([kFIRMessagingRawDataKey isEqualToString:key] && + [val isKindOfClass:[NSData class]]) { + NSData *rawData = (NSData *)val; + [stanza setRawData:[rawData copy]]; + size += [rawData length]; + } else { + FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager009, @"Ignoring key: %@", + key); + } + } + return size; +} + +/** + * Notify the messenger that send data message completed with success. This is called for + * TTL=0, after the message has been sent, or when message is saved, to unlock the send() + * method. + */ +- (void)willSendDataMessageSuccess:(GtalkDataMessageStanza *)stanza + withMessageId:(NSString *)messageId { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager010, + @"send message success: %@", messageId); + [self.delegate willSendDataMessageWithID:messageId error:nil]; +} + +/** + * We send 'send failures' from server as normal FIRMessaging messages, with a 'message_type' + * extra - same as 'message deleted'. + * + * For TTL=0 or errors that can be detected during send ( too many messages, invalid, etc) + * we throw IOExceptions + */ +- (void)willSendDataMessageFail:(GtalkDataMessageStanza *)stanza + withMessageId:(NSString *)messageId + error:(FIRMessagingInternalErrorCode)errorCode { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager011, + @"Send message fail: %@ error: %lu", messageId, (unsigned long)errorCode); + + NSError *error = [NSError errorWithFCMErrorCode:errorCode]; + if ([self.delegate respondsToSelector:@selector(willSendDataMessageWithID:error:)]) { + [self.delegate willSendDataMessageWithID:messageId error:error]; + } +} + +- (void)resendMessagesWithConnection:(FIRMessagingConnection *)connection { + NSMutableString *rmqIdsResent = [NSMutableString string]; + NSMutableArray *toRemoveRmqIds = [NSMutableArray array]; + FIRMessaging_WEAKIFY(self); + FIRMessaging_WEAKIFY(connection); + FIRMessagingRmqMessageHandler messageHandler = ^(int64_t rmqId, int8_t tag, NSData *data) { + FIRMessaging_STRONGIFY(self); + FIRMessaging_STRONGIFY(connection); + GPBMessage *proto = + [FIRMessagingGetClassForTag((FIRMessagingProtoTag)tag) parseFromData:data error:NULL]; + if ([proto isKindOfClass:GtalkDataMessageStanza.class]) { + GtalkDataMessageStanza *stanza = (GtalkDataMessageStanza *)proto; + + if (![self handleExpirationForDataMessage:stanza]) { + // time expired let's delete from RMQ + [toRemoveRmqIds addObject:stanza.persistentId]; + return; + } + [rmqIdsResent appendString:[NSString stringWithFormat:@"%@,", stanza.id_p]]; + } + + [connection sendProto:proto]; + }; + [self.rmq2Manager scanWithRmqMessageHandler:messageHandler + dataMessageHandler:nil]; + + if ([rmqIdsResent length]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager012, @"Resent: %@", + rmqIdsResent); + } + + if ([toRemoveRmqIds count]) { + [self.rmq2Manager removeRmqMessagesWithRmqIds:toRemoveRmqIds]; + } +} + +/** + * Check the TTL and generate an error if needed. + * + * @return false if the message needs to be deleted + */ +- (BOOL)handleExpirationForDataMessage:(GtalkDataMessageStanza *)message { + if (message.ttl == 0) { + return NO; + } + + int64_t now = FIRMessagingCurrentTimestampInSeconds(); + if (now > message.sent + message.ttl) { + [self willSendDataMessageFail:message + withMessageId:message.id_p + error:kFIRMessagingErrorServiceNotAvailable]; + return NO; + } + return YES; +} + +#pragma mark - Private + +- (int)delayForMessage:(NSMutableDictionary *)message { + int delay = 0; // default + if (message[kFIRMessagingSendDelay]) { + delay = [message[kFIRMessagingSendDelay] intValue]; + [message removeObjectForKey:kFIRMessagingSendDelay]; + if (delay < kMinDelaySeconds) { + delay = 0; + } else if (delay > kMaxDelaySeconds) { + delay = kMaxDelaySeconds; + } + } + return delay; +} + +// return True if successfully delayed else False +- (BOOL)delayMessage:(GtalkDataMessageStanza *)message { + return [self.delayedMessagesQueue queueMessage:message]; +} + +- (BOOL)tryToSendDataMessageStanza:(GtalkDataMessageStanza *)stanza { + if (self.client.isConnectionActive) { + [self.client sendMessage:stanza]; + return YES; + } + + // if we only reconnect for TTL = 0 messages check if we ttl = 0 or + // if we reconnect for all messages try to reconnect + if ((self.upstreamForceReconnect == kUpstreamForceReconnectTTL0 && stanza.ttl == 0) || + self.upstreamForceReconnect == kUpstreamForceReconnectAll) { + BOOL isNetworkAvailable = [[FIRMessaging messaging] isNetworkAvailable]; + if (isNetworkAvailable) { + if (stanza.ttl == 0) { + // Add TTL = 0 messages to be sent on next connect. TTL != 0 messages are + // persisted, and will be sent from the RMQ. + [self.client sendOnConnectOrDrop:stanza]; + } + + [self.client retryConnectionImmediately:YES]; + return YES; + } + } + return NO; +} + +- (NSString *)categoryForUpstreamMessages { + return FIRMessagingAppIdentifier(); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDefines.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDefines.h new file mode 100644 index 0000000..abf79a5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDefines.h @@ -0,0 +1,84 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRMessaging_xcodeproj_FIRMessagingDefines_h +#define FIRMessaging_xcodeproj_FIRMessagingDefines_h + +#define _FIRMessaging_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRMessaging_VERBOSE_LOGGING) +#define FIRMessaging_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRMessaging_DEV_VERBOSE_LOG(...) do { } while (0) +#endif // FIRMessaging_VERBOSE_LOGGING + + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRMessaging_WEAKNAME(VAR) VAR ## _weak_ + +#define FIRMessaging_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRMessaging_WEAKNAME(VAR) = (VAR); + +#define FIRMessaging_STRONGIFY(VAR) \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wshadow\"") \ +__strong __typeof__(VAR) VAR = _FIRMessaging_WEAKNAME(VAR); \ +_Pragma("clang diagnostic pop") + + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRMessaging_L +#define _FIRMessaging_L(v) (long)(v) +#endif + +#ifndef _FIRMessaging_UL +#define _FIRMessaging_UL(v) (unsigned long)(v) +#endif + +#endif + +// Debug Assert +#ifndef _FIRMessagingDevAssert +// we directly invoke the NSAssert handler so we can pass on the varargs +// (NSAssert doesn't have a macro we can use that takes varargs) +#ifdef DEBUG +#define _FIRMessagingDevAssert(condition, ...) \ + do { \ + if (!(condition)) { \ + [[NSAssertionHandler currentHandler] \ + handleFailureInFunction:(NSString *) \ + [NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ + file:(NSString *)[NSString stringWithUTF8String:__FILE__] \ + lineNumber:__LINE__ \ + description:__VA_ARGS__]; \ + } \ + } while(0) +#else // !defined(DEBUG) +#define _FIRMessagingDevAssert(condition, ...) do { } while (0) +#endif // !defined(DEBUG) + +#endif // _FIRMessagingDevAssert + +// Invalidates the initializer from which it's called. +#ifndef FIRMessagingInvalidateInitializer +#define FIRMessagingInvalidateInitializer() \ + do { \ + [self class]; /* Avoid warning of dead store to |self|. */ \ + _FIRMessagingDevAssert(NO, @"Invalid initializer."); \ + return nil; \ + } while (0) +#endif diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.h new file mode 100644 index 0000000..d20ec91 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GtalkDataMessageStanza; +@class FIRMessagingRmqManager; + +@protocol FIRMessagingRmqScanner; + +typedef void(^FIRMessagingSendDelayedMessagesHandler)(NSArray *messages); + +@interface FIRMessagingDelayedMessageQueue : NSObject + +- (instancetype)initWithRmqScanner:(id)rmqScanner + sendDelayedMessagesHandler:(FIRMessagingSendDelayedMessagesHandler)sendDelayedMessagesHandler; + +- (BOOL)queueMessage:(GtalkDataMessageStanza *)message; + +- (NSArray *)removeDelayedMessages; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.m new file mode 100644 index 0000000..0371c02 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.m @@ -0,0 +1,146 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingDelayedMessageQueue.h" + +#import "Protos/GtalkCore.pbobjc.h" + +#import "FIRMessagingDefines.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingUtilities.h" + +static const int kMaxQueuedMessageCount = 10; + +@interface FIRMessagingDelayedMessageQueue () + +@property(nonatomic, readonly, weak) id rmqScanner; +@property(nonatomic, readonly, copy) FIRMessagingSendDelayedMessagesHandler sendDelayedMessagesHandler; + +@property(nonatomic, readwrite, assign) int persistedMessageCount; +// the scheduled timeout or -1 if not set +@property(nonatomic, readwrite, assign) int64_t scheduledTimeoutMilliseconds; +// The time of the last scan of the message DB, +// used to avoid retrieving messages more than once. +@property(nonatomic, readwrite, assign) int64_t lastDBScanTimestampSeconds; + +@property(nonatomic, readwrite, strong) NSMutableArray *messages; +@property(nonatomic, readwrite, strong) NSTimer *sendTimer; + +@end + +@implementation FIRMessagingDelayedMessageQueue + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithRmqScanner:(id)rmqScanner + sendDelayedMessagesHandler:(FIRMessagingSendDelayedMessagesHandler)sendDelayedMessagesHandler { + _FIRMessagingDevAssert(sendDelayedMessagesHandler, @"Invalid nil callback for delayed messages"); + self = [super init]; + if (self) { + _rmqScanner = rmqScanner; + _sendDelayedMessagesHandler = sendDelayedMessagesHandler; + _messages = [NSMutableArray arrayWithCapacity:10]; + _scheduledTimeoutMilliseconds = -1; + } + return self; +} + +- (BOOL)queueMessage:(GtalkDataMessageStanza *)message { + if (self.messages.count >= kMaxQueuedMessageCount) { + return NO; + } + if (message.ttl == 0) { + // ttl=0 messages aren't persisted, add it to memory + [self.messages addObject:message]; + } else { + self.persistedMessageCount++; + } + int64_t timeoutMillis = [self calculateTimeoutInMillisWithDelayInSeconds:message.maxDelay]; + if (![self isTimeoutScheduled] || timeoutMillis < self.scheduledTimeoutMilliseconds) { + [self scheduleTimeoutInMillis:timeoutMillis]; + } + return YES; +} + +- (NSArray *)removeDelayedMessages { + [self cancelTimeout]; + if ([self messageCount] == 0) { + return @[]; + } + + NSMutableArray *delayedMessages = [NSMutableArray array]; + // add the ttl=0 messages + if (self.messages.count) { + [delayedMessages addObjectsFromArray:delayedMessages]; + [self.messages removeAllObjects]; + } + + // add persistent messages + if (self.persistedMessageCount > 0) { + FIRMessaging_WEAKIFY(self); + [self.rmqScanner scanWithRmqMessageHandler:nil + dataMessageHandler:^(int64_t rmqId, GtalkDataMessageStanza *stanza) { + FIRMessaging_STRONGIFY(self); + if ([stanza hasMaxDelay] && + [stanza sent] >= self.lastDBScanTimestampSeconds) { + [delayedMessages addObject:stanza]; + } + }]; + self.lastDBScanTimestampSeconds = FIRMessagingCurrentTimestampInSeconds(); + self.persistedMessageCount = 0; + } + return delayedMessages; +} + +- (void)sendMessages { + if (self.sendDelayedMessagesHandler) { + self.sendDelayedMessagesHandler([self removeDelayedMessages]); + } +} + +#pragma mark - Private + +- (NSInteger)messageCount { + return self.messages.count + self.persistedMessageCount; +} + +- (BOOL)isTimeoutScheduled { + return self.scheduledTimeoutMilliseconds > 0; +} + +- (int64_t)calculateTimeoutInMillisWithDelayInSeconds:(int)delay { + return FIRMessagingCurrentTimestampInMilliseconds() + delay * 1000.0; +} + +- (void)scheduleTimeoutInMillis:(int64_t)time { + [self cancelTimeout]; + self.scheduledTimeoutMilliseconds = time; + double delay = (time - FIRMessagingCurrentTimestampInMilliseconds()) / 1000.0; + [self performSelector:@selector(sendMessages) withObject:self afterDelay:delay]; +} + +- (void)cancelTimeout { + if ([self isTimeoutScheduled]) { + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(sendMessages) + object:nil]; + self.scheduledTimeoutMilliseconds = -1; + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingExtensionHelper.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingExtensionHelper.m new file mode 100644 index 0000000..7b436e3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingExtensionHelper.m @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + #import "FIRMessagingExtensionHelper.h" + + #import "FIRMMessageCode.h" +#import "FIRMessagingLogger.h" + + static NSString *const kPayloadOptionsName = @"fcm_options"; +static NSString *const kPayloadOptionsImageURLName = @"image"; + + @interface FIRMessagingExtensionHelper () +@property(nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver); +@property(nonatomic, strong) UNMutableNotificationContent *bestAttemptContent; + + @end + + @implementation FIRMessagingExtensionHelper + + - (void)populateNotificationContent:(UNMutableNotificationContent *)content + withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler { + self.contentHandler = [contentHandler copy]; + self.bestAttemptContent = content; + + NSString *currentImageURL = content.userInfo[kPayloadOptionsName][kPayloadOptionsImageURLName]; + if (!currentImageURL) { + [self deliverNotification]; + return; + } +#if TARGET_OS_IOS + NSURL *attachmentURL = [NSURL URLWithString:currentImageURL]; + if (attachmentURL) { + [self loadAttachmentForURL:attachmentURL + completionHandler:^(UNNotificationAttachment *attachment) { + self.bestAttemptContent.attachments = @[ attachment ]; + [self deliverNotification]; + }]; + } else { + FIRMessagingLoggerError(kFIRMessagingServiceExtensionImageInvalidURL, + @"The Image URL provided is invalid %@.", currentImageURL); + [self deliverNotification]; + } +#else + [self deliverNotification]; +#endif +} + + #if TARGET_OS_IOS +- (void)loadAttachmentForURL:(NSURL *)attachmentURL + completionHandler:(void (^)(UNNotificationAttachment *))completionHandler { + __block UNNotificationAttachment *attachment = nil; + + NSURLSession *session = [NSURLSession + sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + [[session + downloadTaskWithURL:attachmentURL + completionHandler:^(NSURL *temporaryFileLocation, NSURLResponse *response, NSError *error) { + if (error != nil) { + FIRMessagingLoggerError(kFIRMessagingServiceExtensionImageNotDownloaded, + @"Failed to download image given URL %@, error: %@\n", + attachmentURL, error); + completionHandler(attachment); + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *fileExtension = + [NSString stringWithFormat:@".%@", [response.suggestedFilename pathExtension]]; + NSURL *localURL = [NSURL + fileURLWithPath:[temporaryFileLocation.path stringByAppendingString:fileExtension]]; + [fileManager moveItemAtURL:temporaryFileLocation toURL:localURL error:&error]; + if (error) { + FIRMessagingLoggerError( + kFIRMessagingServiceExtensionLocalFileNotCreated, + @"Failed to move the image file to local location: %@, error: %@\n", localURL, + error); + completionHandler(attachment); + return; + } + + attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" + URL:localURL + options:nil + error:&error]; + if (error) { + FIRMessagingLoggerError(kFIRMessagingServiceExtensionImageNotAttached, + @"Failed to create attachment with URL %@, error: %@\n", + localURL, error); + completionHandler(attachment); + return; + } + completionHandler(attachment); + }] resume]; +} +#endif + + - (void)deliverNotification { + if (self.contentHandler) { + self.contentHandler(self.bestAttemptContent); + } +} + + @end + diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.h new file mode 100644 index 0000000..223ac9c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.h @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRMessagingLoggerInfo + +// Convenience macros that log to the shared FIRMessagingLogger instance. These macros +// are how users should typically log to FIRMessagingLogger. +#define FIRMessagingLoggerDebug(code, ...) \ + [FIRMessagingSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerInfo(code, ...) \ + [FIRMessagingSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerNotice(code, ...) \ + [FIRMessagingSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerWarn(code, ...) \ + [FIRMessagingSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerError(code, ...) \ + [FIRMessagingSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRMessagingLoggerInfo) + +@interface FIRMessagingLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared FIRMessagingLogger used exclusively + * for FIRMessaging log messages. + * + * @return the shared FIRMessagingLogger instance + */ +FIRMessagingLogger *FIRMessagingSharedLogger(void); diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.m new file mode 100644 index 0000000..d3c96d2 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.m @@ -0,0 +1,95 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingLogger.h" + +#import + +FIRLoggerService kFIRLoggerMessaging = @"[Firebase/Messaging]"; + +@implementation FIRMessagingLogger + ++ (instancetype)standardLogger { + return [[FIRMessagingLogger alloc] init]; +} + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRMessagingMessageCode)messageCode { + return [NSString stringWithFormat:@"I-FCM%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRMessagingLogger *FIRMessagingSharedLogger(void) { + static dispatch_once_t onceToken; + static FIRMessagingLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [FIRMessagingLogger standardLogger]; + }); + + return logger; +} diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.h new file mode 100644 index 0000000..1f528ab --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRMessagingPacket : NSObject + ++ (FIRMessagingPacket *)packetWithTag:(int8_t)tag rmqId:(NSString *)rmqId data:(NSData *)data; + +@property(nonatomic, readonly, strong) NSData *data; +@property(nonatomic, readonly, assign) int8_t tag; +// not sent over the wire required for bookkeeping +@property(nonatomic, readonly, assign) NSString *rmqId; + +@end + + +/** + * A queue of the packets(protos) that need to be send over the wire. + */ +@interface FIRMessagingPacketQueue : NSObject + +@property(nonatomic, readonly, assign) NSUInteger count; +@property(nonatomic, readonly, assign) BOOL isEmpty; + +- (void)push:(FIRMessagingPacket *)packet; +- (void)pushHead:(FIRMessagingPacket *)packet; +- (FIRMessagingPacket *)pop; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.m new file mode 100644 index 0000000..2b3410a --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.m @@ -0,0 +1,103 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPacketQueue.h" + +#import "FIRMessagingDefines.h" + +@interface FIRMessagingPacket () + +@property(nonatomic, readwrite, strong) NSData *data; +@property(nonatomic, readwrite, assign) int8_t tag; +@property(nonatomic, readwrite, assign) NSString *rmqId; + +@end + +@implementation FIRMessagingPacket + ++ (FIRMessagingPacket *)packetWithTag:(int8_t)tag rmqId:(NSString *)rmqId data:(NSData *)data { + return [[self alloc] initWithTag:tag rmqId:rmqId data:data]; +} + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithTag:(int8_t)tag rmqId:(NSString *)rmqId data:(NSData *)data { + self = [super init]; + if (self != nil) { + _data = data; + _tag = tag; + _rmqId = rmqId; + } + return self; +} + +- (NSString *)description { + if ([self.rmqId length]) { + return [NSString stringWithFormat:@", RmqId - %@", + self.tag, _FIRMessaging_UL(self.data.length), self.rmqId]; + } else { + return [NSString stringWithFormat:@"", + self.tag, _FIRMessaging_UL(self.data.length)]; + } +} + +@end + +@interface FIRMessagingPacketQueue () + +@property(nonatomic, readwrite, strong) NSMutableArray *packetsContainer; + +@end + + +@implementation FIRMessagingPacketQueue; + +- (id)init { + self = [super init]; + if (self) { + _packetsContainer = [[NSMutableArray alloc] init]; + } + return self; +} + +- (BOOL)isEmpty { + return self.packetsContainer.count == 0; +} + +- (NSUInteger)count { + return self.packetsContainer.count; +} + +- (void)push:(FIRMessagingPacket *)packet { + [self.packetsContainer addObject:packet]; +} + +- (void)pushHead:(FIRMessagingPacket *)packet { + [self.packetsContainer insertObject:packet atIndex:0]; +} + +- (FIRMessagingPacket *)pop { + if (!self.isEmpty) { + FIRMessagingPacket *packet = self.packetsContainer[0]; + [self.packetsContainer removeObjectAtIndex:0]; + return packet; + } + return nil; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.h new file mode 100644 index 0000000..a8108bf --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingTopicsCommon.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents a single batch of topics, with the same action. + * + * Topic operations which have the same action (subscribe or unsubscribe) can be executed + * simultaneously, as the order of operations do not matter with the same action. The set of + * topics is unique, as it doesn't make sense to apply the same action to the same topic + * repeatedly; the result would be the same as the first time. + */ +@interface FIRMessagingTopicBatch : NSObject + +@property(nonatomic, readonly, assign) FIRMessagingTopicAction action; +@property(nonatomic, readonly, copy) NSMutableSet *topics; + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithAction:(FIRMessagingTopicAction)action NS_DESIGNATED_INITIALIZER; + +@end + +@class FIRMessagingPendingTopicsList; +/** + * This delegate must be supplied to the instance of FIRMessagingPendingTopicsList, via the + * @cdelegate property. It lets the + * pending topics list know whether or not it can begin making requests via + * @c-pendingTopicsListCanRequestTopicUpdates:, and handles the request to actually + * perform the topic operation. The delegate also handles when the pending topics list is updated, + * so that it can be archived or persisted. + * + * @see FIRMessagingPendingTopicsList + */ +@protocol FIRMessagingPendingTopicsListDelegate + +- (void)pendingTopicsList:(FIRMessagingPendingTopicsList *)list + requestedUpdateForTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + completion:(FIRMessagingTopicOperationCompletion)completion; +- (void)pendingTopicsListDidUpdate:(FIRMessagingPendingTopicsList *)list; +- (BOOL)pendingTopicsListCanRequestTopicUpdates:(FIRMessagingPendingTopicsList *)list; + +@end + +/** + * FIRMessagingPendingTopicsList manages a list of topic subscription updates, batched by the same + * action (subscribe or unsubscribe). The list roughly maintains the order of the topic operations, + * batched together whenever the topic action (subscribe or unsubscribe) changes. + * + * Topics operations are batched by action because it is safe to perform the same topic action + * (subscribe or unsubscribe) on many topics simultaneously. After each batch is successfully + * completed, the next batch operations can begin. + * + * When asked to resume its operations, FIRMessagingPendingTopicsList will begin performing updates + * of its current batch of topics. For example, it may begin subscription operations for topics + * [A, B, C] simultaneously. + * + * When the current batch is completed, the next batch of operations will be started. For example + * the list may begin unsubscribe operations for [D, A, E]. Note that because A is in both batches, + * A will be correctly subscribed in the first batch, then unsubscribed as part of the second batch + * of operations. Without batching, it would be ambiguous whether A's subscription operation or the + * unsubscription operation would be completed first. + * + * An app can subscribe and unsubscribe from many topics, and this class helps persist the pending + * topics and perform the operation safely and correctly. + * + * When a topic fails to subscribe or unsubscribe due to a network error, it is considered a + * recoverable error, and so it remains in the current batch until it is succesfully completed. + * Topic updates are completed when they either (a) succeed, (b) are cancelled, or (c) result in an + * unrecoverable error. Any error outside of `NSURLErrorDomain` is considered an unrecoverable + * error. + * + * In addition to maintaining the list of pending topic updates, FIRMessagingPendingTopicsList also + * can track completion handlers for topic operations. + * + * @discussion Completion handlers for topic updates are not maintained if it was restored from a + * keyed archive. They are only called if the topic operation finished within the same app session. + * + * You must supply an object conforming to FIRMessagingPendingTopicsListDelegate in order for the + * topic operations to execute. + * + * @see FIRMessagingPendingTopicsListDelegate + */ +@interface FIRMessagingPendingTopicsList : NSObject + +@property(nonatomic, weak) NSObject *delegate; + +@property(nonatomic, readonly, strong, nullable) NSDate *archiveDate; +@property(nonatomic, readonly) NSUInteger numberOfBatches; + + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (void)addOperationForTopic:(NSString *)topic + withAction:(FIRMessagingTopicAction)action + completion:(nullable FIRMessagingTopicOperationCompletion)completion; +- (void)resumeOperationsIfNeeded; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.m new file mode 100644 index 0000000..b10b552 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.m @@ -0,0 +1,265 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPendingTopicsList.h" + +#import "FIRMessaging_Private.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPubSub.h" + +#import "FIRMessagingDefines.h" + +NSString *const kPendingTopicBatchActionKey = @"action"; +NSString *const kPendingTopicBatchTopicsKey = @"topics"; + +NSString *const kPendingBatchesEncodingKey = @"batches"; +NSString *const kPendingTopicsTimestampEncodingKey = @"ts"; + +#pragma mark - FIRMessagingTopicBatch + +@interface FIRMessagingTopicBatch () + +@property(nonatomic, strong, nonnull) NSMutableDictionary + *> *topicHandlers; + +@end + +@implementation FIRMessagingTopicBatch + +- (instancetype)initWithAction:(FIRMessagingTopicAction)action { + if (self = [super init]) { + _action = action; + _topics = [NSMutableSet set]; + _topicHandlers = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark NSCoding + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInteger:self.action forKey:kPendingTopicBatchActionKey]; + [aCoder encodeObject:self.topics forKey:kPendingTopicBatchTopicsKey]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + + // Ensure that our integer -> enum casting is safe + NSInteger actionRawValue = [aDecoder decodeIntegerForKey:kPendingTopicBatchActionKey]; + FIRMessagingTopicAction action = FIRMessagingTopicActionSubscribe; + if (actionRawValue == FIRMessagingTopicActionUnsubscribe) { + action = FIRMessagingTopicActionUnsubscribe; + } + + if (self = [self initWithAction:action]) { + NSSet *topics = [aDecoder decodeObjectForKey:kPendingTopicBatchTopicsKey]; + if ([topics isKindOfClass:[NSSet class]]) { + _topics = [topics mutableCopy]; + } + _topicHandlers = [NSMutableDictionary dictionary]; + } + return self; +} + +@end + +#pragma mark - FIRMessagingPendingTopicsList + +@interface FIRMessagingPendingTopicsList () + +@property(nonatomic, readwrite, strong) NSDate *archiveDate; +@property(nonatomic, strong) NSMutableArray *topicBatches; + +@property(nonatomic, strong) FIRMessagingTopicBatch *currentBatch; +@property(nonatomic, strong) NSMutableSet *topicsInFlight; + +@end + +@implementation FIRMessagingPendingTopicsList + +- (instancetype)init { + if (self = [super init]) { + _topicBatches = [NSMutableArray array]; + _topicsInFlight = [NSMutableSet set]; + } + return self; +} + ++ (void)pruneTopicBatches:(NSMutableArray *)topicBatches { + // For now, just remove empty batches. In the future we can use this to make the subscriptions + // more efficient, by actually pruning topic actions that cancel each other out, for example. + for (NSInteger i = topicBatches.count-1; i >= 0; i--) { + FIRMessagingTopicBatch *batch = topicBatches[i]; + if (batch.topics.count == 0) { + [topicBatches removeObjectAtIndex:i]; + } + } +} + +#pragma mark NSCoding + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[NSDate date] forKey:kPendingTopicsTimestampEncodingKey]; + [aCoder encodeObject:self.topicBatches forKey:kPendingBatchesEncodingKey]; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + + if (self = [self init]) { + _archiveDate = [aDecoder decodeObjectForKey:kPendingTopicsTimestampEncodingKey]; + NSArray *archivedBatches = [aDecoder decodeObjectForKey:kPendingBatchesEncodingKey]; + if (archivedBatches) { + _topicBatches = [archivedBatches mutableCopy]; + [FIRMessagingPendingTopicsList pruneTopicBatches:_topicBatches]; + } + _topicsInFlight = [NSMutableSet set]; + } + return self; +} + +#pragma mark Getters + +- (NSUInteger)numberOfBatches { + return self.topicBatches.count; +} + +#pragma mark Adding/Removing topics + +- (void)addOperationForTopic:(NSString *)topic + withAction:(FIRMessagingTopicAction)action + completion:(nullable FIRMessagingTopicOperationCompletion)completion { + + FIRMessagingTopicBatch *lastBatch = nil; + @synchronized (self) { + lastBatch = self.topicBatches.lastObject; + if (!lastBatch || lastBatch.action != action) { + // There either was no last batch, or our last batch's action was not the same, so we have to + // create a new batch + lastBatch = [[FIRMessagingTopicBatch alloc] initWithAction:action]; + [self.topicBatches addObject:lastBatch]; + } + BOOL topicExistedBefore = ([lastBatch.topics member:topic] != nil); + if (!topicExistedBefore) { + [lastBatch.topics addObject:topic]; + [self.delegate pendingTopicsListDidUpdate:self]; + } + // Add the completion handler to the batch + if (completion) { + NSMutableArray *handlers = lastBatch.topicHandlers[topic]; + if (!handlers) { + handlers = [[NSMutableArray alloc] init]; + } + [handlers addObject:completion]; + lastBatch.topicHandlers[topic] = handlers; + } + if (!self.currentBatch) { + self.currentBatch = lastBatch; + } + // This may have been the first topic added, or was added to an ongoing batch + if (self.currentBatch == lastBatch && !topicExistedBefore) { + // Add this topic to our ongoing operations + FIRMessaging_WEAKIFY(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + FIRMessaging_STRONGIFY(self); + [self resumeOperationsIfNeeded]; + }); + } + } +} + +- (void)resumeOperationsIfNeeded { + @synchronized (self) { + // If current batch is not set, set it now + if (!self.currentBatch) { + self.currentBatch = self.topicBatches.firstObject; + } + if (self.currentBatch.topics.count == 0) { + return; + } + if (!self.delegate) { + FIRMessagingLoggerError(kFIRMessagingMessageCodePendingTopicsList000, + @"Attempted to update pending topics without a delegate"); + return; + } + if (![self.delegate pendingTopicsListCanRequestTopicUpdates:self]) { + return; + } + for (NSString *topic in self.currentBatch.topics) { + if ([self.topicsInFlight member:topic]) { + // This topic is already active, so skip + continue; + } + [self beginUpdateForCurrentBatchTopic:topic]; + } + } +} + +- (BOOL)subscriptionErrorIsRecoverable:(NSError *)error { + return [error.domain isEqualToString:NSURLErrorDomain]; +} + +- (void)beginUpdateForCurrentBatchTopic:(NSString *)topic { + + @synchronized (self) { + [self.topicsInFlight addObject:topic]; + } + FIRMessaging_WEAKIFY(self); + [self.delegate + pendingTopicsList:self + requestedUpdateForTopic:topic + action:self.currentBatch.action + completion:^(NSError *error) { + dispatch_async( + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + FIRMessaging_STRONGIFY(self); + @synchronized(self) { + [self.topicsInFlight removeObject:topic]; + + BOOL recoverableError = [self subscriptionErrorIsRecoverable:error]; + if (!error || !recoverableError) { + // Notify our handlers and remove the topic from our batch + NSMutableArray *handlers = self.currentBatch.topicHandlers[topic]; + if (handlers.count) { + dispatch_async(dispatch_get_main_queue(), ^{ + for (FIRMessagingTopicOperationCompletion handler in handlers) { + handler(error); + } + [handlers removeAllObjects]; + }); + } + [self.currentBatch.topics removeObject:topic]; + [self.currentBatch.topicHandlers removeObjectForKey:topic]; + if (self.currentBatch.topics.count == 0) { + // All topic updates successfully finished in this batch, move on + // to the next batch + [self.topicBatches removeObject:self.currentBatch]; + self.currentBatch = nil; + } + [self.delegate pendingTopicsListDidUpdate:self]; + FIRMessaging_WEAKIFY(self); + dispatch_async( + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), + ^{ + FIRMessaging_STRONGIFY(self); + [self resumeOperationsIfNeeded]; + }); + } + } + }); + }]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.h new file mode 100644 index 0000000..5a48e99 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRMessagingPersistentSyncMessage : NSObject + +@property(nonatomic, readonly, strong) NSString *rmqID; +@property(nonatomic, readwrite, assign) BOOL apnsReceived; +@property(nonatomic, readwrite, assign) BOOL mcsReceived; +@property(nonatomic, readonly, assign) int64_t expirationTime; + +- (instancetype)initWithRMQID:(NSString *)rmqID expirationTime:(int64_t)expirationTime; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.m new file mode 100644 index 0000000..bf7d05b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.m @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPersistentSyncMessage.h" + +#import "FIRMessagingDefines.h" + +@interface FIRMessagingPersistentSyncMessage () + +@property(nonatomic, readwrite, strong) NSString *rmqID; +@property(nonatomic, readwrite, assign) int64_t expirationTime; + +@end + +@implementation FIRMessagingPersistentSyncMessage + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithRMQID:(NSString *)rmqID expirationTime:(int64_t)expirationTime { + self = [super init]; + if (self) { + _rmqID = [rmqID copy]; + _expirationTime = expirationTime; + } + return self; +} + +- (NSString *)description { + NSString *classDescription = NSStringFromClass([self class]); + NSDate *date = [NSDate dateWithTimeIntervalSince1970:self.expirationTime]; + return [NSString stringWithFormat:@"%@: (rmqID: %@, apns: %d, mcs: %d, expiry: %@", + classDescription, self.rmqID, self.mcsReceived, self.apnsReceived, date]; +} + +- (NSString *)debugDescription { + return [self description]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.h new file mode 100644 index 0000000..2c2fbe6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.h @@ -0,0 +1,171 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRMessagingClient; +@class FIRMessagingPubSubCache; + +/** + * FIRMessagingPubSub provides a publish-subscribe model for sending FIRMessaging topic messages. + * + * An app can subscribe to different topics defined by the + * developer. The app server can then send messages to the subscribed devices + * without having to maintain topic-subscribers mapping. Topics do not + * need to be explicitly created before subscribing or publishing—they + * are automatically created when publishing or subscribing. + * + * Messages published to the topic will be received as regular FIRMessaging messages + * with `"from"` set to `"/topics/myTopic"`. + * + * Only topic names that match the pattern `"/topics/[a-zA-Z0-9-_.~%]{1,900}"` + * are allowed for subscribing and publishing. + */ +@interface FIRMessagingPubSub : NSObject + +@property(nonatomic, readonly, strong) FIRMessagingPubSubCache *cache; +@property(nonatomic, readonly, strong) FIRMessagingClient *client; + +/** + * Initializes an instance of FIRMessagingPubSub. + * + * @return An instance of FIRMessagingPubSub. + */ +- (instancetype)initWithClient:(FIRMessagingClient *)client NS_DESIGNATED_INITIALIZER; + +/** + * Subscribes an app instance to a topic, enabling it to receive messages + * sent to that topic. + * + * This is an asynchronous call. If subscription fails, FIRMessaging + * invokes the completion callback with the appropriate error. + * + * @see FIRMessagingPubSub unsubscribeWithToken:topic:handler: + * + * @param token The registration token as received from the InstanceID + * library for a given `authorizedEntity` and "gcm" scope. + * @param topic The topic to subscribe to. Should be of the form + * `"/topics/"`. + * @param options Unused parameter, please pass nil or empty dictionary. + * @param handler The callback handler invoked when the subscribe call + * ends. In case of success, a nil error is returned. Otherwise, + * an appropriate error object is returned. + * @discussion This method is thread-safe. However, it is not guaranteed to + * return on the main thread. + */ +- (void)subscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(nullable NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler; + +/** + * Unsubscribes an app instance from a topic, stopping it from receiving + * any further messages sent to that topic. + * + * This is an asynchronous call. If the attempt to unsubscribe fails, + * we invoke the `completion` callback passed in with an appropriate error. + * + * @param token The token used to subscribe to this topic. + * @param topic The topic to unsubscribe from. Should be of the form + * `"/topics/"`. + * @param options Unused parameter, please pass nil or empty dictionary. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + * @discussion This method is thread-safe. However, it is not guaranteed to + * return on the main thread. + */ +- (void)unsubscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(nullable NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler; + +/** + * Asynchronously subscribe to the topic. Adds to the pending list of topic operations. + * Retry in case of failures. This makes a repeated attempt to subscribe to the topic + * as compared to the `subscribe` method above which tries once. + * + * @param topic The topic name to subscribe to. Should be of the form `"/topics/"`. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)subscribeToTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler; + +/** + * Asynchronously unsubscribe from the topic. Adds to the pending list of topic operations. + * Retry in case of failures. This makes a repeated attempt to unsubscribe from the topic + * as compared to the `unsubscribe` method above which tries once. + * + * @param topic The topic name to unsubscribe from. Should be of the form `"/topics/"`. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)unsubscribeFromTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler; + +/** + * Schedule subscriptions sync. + * + * @param immediately YES if the sync should be scheduled immediately else NO if we can delay + * the sync. + */ +- (void)scheduleSync:(BOOL)immediately; + +/** + * Adds the "/topics/" prefix to the topic. + * + * @param topic The topic to add the prefix to. + * + * @return The new topic name with the "/topics/" prefix added. + */ ++ (NSString *)addPrefixToTopic:(NSString *)topic; + +/** + * Removes the "/topics/" prefix from the topic. + * + * @param topic The topic to remove the prefix from. + * + * @return The new topic name with the "/topics/" prefix removed. + */ + ++ (NSString *)removePrefixFromTopic:(NSString *)topic; + +/** + * Check if the topic name has "/topics/" prefix. + * + * @param topic The topic name to verify. + * + * @return YES if the topic name has "/topics/" prefix else NO. + */ ++ (BOOL)hasTopicsPrefix:(NSString *)topic; + +/** + * Check if it's a valid topic name. This includes "/topics/" prefix in the topic name. + * + * @param topic The topic name to verify. + * + * @return YES if the topic name satisfies the regex "/topics/[a-zA-Z0-9-_.~%]{1,900}". + */ ++ (BOOL)isValidTopicWithPrefix:(NSString *)topic; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.m new file mode 100644 index 0000000..0fad4a0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.m @@ -0,0 +1,282 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPubSub.h" + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingClient.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPendingTopicsList.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessaging_Private.h" +#import "NSDictionary+FIRMessaging.h" +#import "NSError+FIRMessaging.h" + +static NSString *const kPendingSubscriptionsListKey = + @"com.firebase.messaging.pending-subscriptions"; + +@interface FIRMessagingPubSub () + +@property(nonatomic, readwrite, strong) FIRMessagingPendingTopicsList *pendingTopicUpdates; +@property(nonatomic, readwrite, strong) FIRMessagingClient *client; + +@end + +@implementation FIRMessagingPubSub + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); + // Need this to disable an Xcode warning. + return [self initWithClient:nil]; +} + +- (instancetype)initWithClient:(FIRMessagingClient *)client { + self = [super init]; + if (self) { + _client = client; + [self restorePendingTopicsList]; + } + return self; +} + +- (void)subscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler { + _FIRMessagingDevAssert([token length], @"FIRMessaging error no token specified"); + _FIRMessagingDevAssert([topic length], @"FIRMessaging error Invalid empty topic specified"); + if (!self.client) { + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubFIRMessagingNotSetup]); + return; + } + + token = [token copy]; + topic = [topic copy]; + + if (![options count]) { + options = @{}; + } + + if (![[self class] isValidTopicWithPrefix:topic]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodePubSub000, + @"Invalid FIRMessaging Pubsub topic %@", topic); + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubInvalidTopic]); + return; + } + + if (![self verifyPubSubOptions:options]) { + // we do not want to quit even if options have some invalid values. + FIRMessagingLoggerError(kFIRMessagingMessageCodePubSub001, + @"Invalid options passed to FIRMessagingPubSub with non-string keys or " + "values."); + } + // copy the dictionary would trim non-string keys or values if any. + options = [options fcm_trimNonStringValues]; + + [self.client updateSubscriptionWithToken:token + topic:topic + options:options + shouldDelete:NO + handler:^void(NSError *error) { + handler(error); + }]; +} + +- (void)unsubscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler { + _FIRMessagingDevAssert([token length], @"FIRMessaging error no token specified"); + _FIRMessagingDevAssert([topic length], @"FIRMessaging error Invalid empty topic specified"); + + if (!self.client) { + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubFIRMessagingNotSetup]); + return; + } + + token = [token copy]; + topic = [topic copy]; + if (![options count]) { + options = @{}; + } + + if (![[self class] isValidTopicWithPrefix:topic]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodePubSub002, + @"Invalid FIRMessaging Pubsub topic %@", topic); + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubInvalidTopic]); + return; + } + if (![self verifyPubSubOptions:options]) { + // we do not want to quit even if options have some invalid values. + FIRMessagingLoggerError( + kFIRMessagingMessageCodePubSub003, + @"Invalid options passed to FIRMessagingPubSub with non-string keys or values."); + } + // copy the dictionary would trim non-string keys or values if any. + options = [options fcm_trimNonStringValues]; + + [self.client updateSubscriptionWithToken:token + topic:topic + options:options + shouldDelete:YES + handler:^void(NSError *error) { + handler(error); + }]; +} + +- (void)subscribeToTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler { + [self.pendingTopicUpdates addOperationForTopic:topic + withAction:FIRMessagingTopicActionSubscribe + completion:handler]; +} + +- (void)unsubscribeFromTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler { + [self.pendingTopicUpdates addOperationForTopic:topic + withAction:FIRMessagingTopicActionUnsubscribe + completion:handler]; +} + +- (void)scheduleSync:(BOOL)immediately { + NSString *fcmToken = [[FIRMessaging messaging] defaultFcmToken]; + if (fcmToken.length) { + [self.pendingTopicUpdates resumeOperationsIfNeeded]; + } +} + +#pragma mark - FIRMessagingPendingTopicsListDelegate + +- (void)pendingTopicsList:(FIRMessagingPendingTopicsList *)list + requestedUpdateForTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + completion:(FIRMessagingTopicOperationCompletion)completion { + + NSString *fcmToken = [[FIRMessaging messaging] defaultFcmToken]; + if (action == FIRMessagingTopicActionSubscribe) { + [self subscribeWithToken:fcmToken topic:topic options:nil handler:completion]; + } else { + [self unsubscribeWithToken:fcmToken topic:topic options:nil handler:completion]; + } +} + +- (void)pendingTopicsListDidUpdate:(FIRMessagingPendingTopicsList *)list { + [self archivePendingTopicsList:list]; +} + +- (BOOL)pendingTopicsListCanRequestTopicUpdates:(FIRMessagingPendingTopicsList *)list { + NSString *fcmToken = [[FIRMessaging messaging] defaultFcmToken]; + return (fcmToken.length > 0); +} + +#pragma mark - Storing Pending Topics + +- (void)archivePendingTopicsList:(FIRMessagingPendingTopicsList *)topicsList { + GULUserDefaults *defaults = [GULUserDefaults standardUserDefaults]; + NSData *pendingData = [NSKeyedArchiver archivedDataWithRootObject:topicsList]; + [defaults setObject:pendingData forKey:kPendingSubscriptionsListKey]; + [defaults synchronize]; +} + +- (void)restorePendingTopicsList { + GULUserDefaults *defaults = [GULUserDefaults standardUserDefaults]; + NSData *pendingData = [defaults objectForKey:kPendingSubscriptionsListKey]; + FIRMessagingPendingTopicsList *subscriptions; + @try { + if (pendingData) { + subscriptions = [NSKeyedUnarchiver unarchiveObjectWithData:pendingData]; + } + } @catch (NSException *exception) { + // Nothing we can do, just continue as if we don't have pending subscriptions + } @finally { + if (subscriptions) { + self.pendingTopicUpdates = subscriptions; + } else { + self.pendingTopicUpdates = [[FIRMessagingPendingTopicsList alloc] init]; + } + self.pendingTopicUpdates.delegate = self; + } +} + +#pragma mark - Private Helpers + +- (BOOL)verifyPubSubOptions:(NSDictionary *)options { + return ![options fcm_hasNonStringKeysOrValues]; +} + +#pragma mark - Topic Name Helpers + +static NSString *const kTopicsPrefix = @"/topics/"; +static NSString *const kTopicRegexPattern = @"/topics/([a-zA-Z0-9-_.~%]+)"; + ++ (NSString *)addPrefixToTopic:(NSString *)topic { + if (![self hasTopicsPrefix:topic]) { + return [NSString stringWithFormat:@"%@%@", kTopicsPrefix, topic]; + } else { + return [topic copy]; + } +} + ++ (NSString *)removePrefixFromTopic:(NSString *)topic { + if ([self hasTopicsPrefix:topic]) { + return [topic substringFromIndex:kTopicsPrefix.length]; + } else { + return [topic copy]; + } +} + ++ (BOOL)hasTopicsPrefix:(NSString *)topic { + return [topic hasPrefix:kTopicsPrefix]; +} + +/** + * Returns a regular expression for matching a topic sender. + * + * @return The topic matching regular expression + */ ++ (NSRegularExpression *)topicRegex { + // Since this is a static regex pattern, we only only need to declare it once. + static NSRegularExpression *topicRegex; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSError *error; + topicRegex = + [NSRegularExpression regularExpressionWithPattern:kTopicRegexPattern + options:NSRegularExpressionAnchorsMatchLines + error:&error]; + }); + return topicRegex; +} + +/** + * Gets the class describing occurences of topic names and sender IDs in the sender. + * + * @param expression The topic expression used to generate a pubsub topic + * + * @return Representation of captured subexpressions in topic regular expression + */ ++ (BOOL)isValidTopicWithPrefix:(NSString *)topic { + NSRange topicRange = NSMakeRange(0, topic.length); + NSRange regexMatchRange = [[self topicRegex] rangeOfFirstMatchInString:topic + options:NSMatchingAnchored + range:topicRange]; + return NSEqualRanges(topicRange, regexMatchRange); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.h new file mode 100644 index 0000000..b51813f --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingTopicOperation.h" + +@class FIRMessagingCheckinService; + +@interface FIRMessagingPubSubRegistrar : NSObject + +/** + * Designated Initializer. + * + * @param checkinService The checkin service used to register with Checkin + * server. + * + * @return A new FIRMessagingPubSubRegistrar instance used to subscribe/unsubscribe. + */ +- (instancetype)initWithCheckinService:(FIRMessagingCheckinService *)checkinService; + +/** + * Stops all the subscription requests going on in parallel. This would + * invalidate all the handlers associated with the subscription requests. + */ +- (void)stopAllSubscriptionRequests; + +/** + * Update subscription status for a given topic with FIRMessaging's backend. + * + * @param topic The topic to subscribe to. + * @param token The registration token to be used. + * @param options The options to be passed in during subscription request. + * @param shouldDelete NO if the subscription is being added else YES if being + * removed. + * @param handler The handler invoked once the update subscription request + * finishes. + */ +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.m new file mode 100644 index 0000000..6268302 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.m @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPubSubRegistrar.h" + +#import "FIRMessagingCheckinService.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingPubSubRegistrar.h" +#import "FIRMessagingTopicsCommon.h" +#import "NSError+FIRMessaging.h" + +@interface FIRMessagingPubSubRegistrar () + +@property(nonatomic, readwrite, strong) FIRMessagingCheckinService *checkinService; + +@property(nonatomic, readonly, strong) NSOperationQueue *topicOperations; +// Common errors, instantiated, to avoid generating multiple copies +@property(nonatomic, readwrite, strong) NSError *operationInProgressError; + +@end + +@implementation FIRMessagingPubSubRegistrar + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithCheckinService:(FIRMessagingCheckinService *)checkinService { + self = [super init]; + if (self) { + _checkinService = checkinService; + _topicOperations = [[NSOperationQueue alloc] init]; + // Do 10 topic operations at a time; it's enough to keep the TCP connection to the host alive, + // saving hundreds of milliseconds on each request (compared to a serial queue). + _topicOperations.maxConcurrentOperationCount = 10; + } + return self; +} + +- (void)stopAllSubscriptionRequests { + [self.topicOperations cancelAllOperations]; +} + +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler { + + FIRMessagingTopicAction action = FIRMessagingTopicActionSubscribe; + if (shouldDelete) { + action = FIRMessagingTopicActionUnsubscribe; + } + FIRMessagingTopicOperation *operation = + [[FIRMessagingTopicOperation alloc] initWithTopic:topic + action:action + token:token + options:options + checkinService:self.checkinService + completion:handler]; + [self.topicOperations addOperation:operation]; + +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.h new file mode 100644 index 0000000..676c7f1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessaging.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRMessagingReceiver; +@class GULUserDefaults; +@protocol FIRMessagingReceiverDelegate + +- (void)receiver:(FIRMessagingReceiver *)receiver + receivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage; + +@end + +@interface FIRMessagingReceiver : NSObject + +@property(nonatomic, weak, nullable) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.m new file mode 100644 index 0000000..4d8ec13 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.m @@ -0,0 +1,103 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingReceiver.h" + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessaging_Private.h" + +static NSString *const kUpstreamMessageIDUserInfoKey = @"messageID"; +static NSString *const kUpstreamErrorUserInfoKey = @"error"; + +static int downstreamMessageID = 0; + +@interface FIRMessagingReceiver () +@property(nonatomic, strong) GULUserDefaults *defaults; +@end + +@implementation FIRMessagingReceiver + +#pragma mark - FIRMessagingDataMessageManager protocol + +- (void)didReceiveMessage:(NSDictionary *)message withIdentifier:(nullable NSString *)messageID { + if (![messageID length]) { + messageID = [[self class] nextMessageID]; + } + + [self handleDirectChannelMessage:message withIdentifier:messageID]; +} + +- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error { + NSNotification *notification; + if (error) { + NSDictionary *userInfo = @{ + kUpstreamMessageIDUserInfoKey : [messageID copy], + kUpstreamErrorUserInfoKey : error + }; + notification = [NSNotification notificationWithName:FIRMessagingSendErrorNotification + object:nil + userInfo:userInfo]; + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver000, + @"Fail to send upstream message: %@ error: %@", messageID, error); + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver001, @"Will send upstream message: %@", + messageID); + } +} + +- (void)didSendDataMessageWithID:(NSString *)messageID { + // invoke the callbacks asynchronously + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver002, @"Did send upstream message: %@", + messageID); + NSNotification * notification = + [NSNotification notificationWithName:FIRMessagingSendSuccessNotification + object:nil + userInfo:@{ kUpstreamMessageIDUserInfoKey : [messageID copy] }]; + + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; +} + +- (void)didDeleteMessagesOnServer { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver003, + @"Will send deleted messages notification"); + NSNotification * notification = + [NSNotification notificationWithName:FIRMessagingMessagesDeletedNotification + object:nil]; + + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; +} + +#pragma mark - Private Helpers +- (void)handleDirectChannelMessage:(NSDictionary *)message withIdentifier:(NSString *)messageID { + FIRMessagingRemoteMessage *wrappedMessage = [[FIRMessagingRemoteMessage alloc] init]; + wrappedMessage.appData = [message copy]; + wrappedMessage.messageID = messageID; + [self.delegate receiver:self receivedRemoteMessage:wrappedMessage]; +} + ++ (NSString *)nextMessageID { + @synchronized (self) { + ++downstreamMessageID; + return [NSString stringWithFormat:@"gcm-%d", downstreamMessageID]; + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.h new file mode 100644 index 0000000..065479c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.h @@ -0,0 +1,80 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" +#import "FIRMessagingCheckinService.h" + +@class FIRMessagingCheckinStore; +@class FIRMessagingPubSubRegistrar; + +/** + * Handle the registration process for the client. Fetch checkin information from the Checkin + * service if not cached on the device and then try to register the client with FIRMessaging backend. + */ +@interface FIRMessagingRegistrar : NSObject + +@property(nonatomic, readonly, strong) FIRMessagingPubSubRegistrar *pubsubRegistrar; +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; + +/** + * Initialize a FIRMessaging Registrar. + * + * @return A FIRMessaging Registrar object. + */ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +#pragma mark - Checkin + +/** + * Try to load checkin info from the disk if not currently loaded into memory. + * + * @return YES if successfully loaded valid checkin info to memory else NO. + */ +- (BOOL)tryToLoadValidCheckinInfo; + +#pragma mark - Subscribe/Unsubscribe + +/** + * Update the subscription for a given topic for the client. + * + * @param topic The topic for which the subscription should be updated. + * @param token The registration token to be used by the client. + * @param options The extra options if any being passed as part of + * subscription request. + * @param shouldDelete YES if we want to delete an existing subscription else NO + * if we want to create a new subscription. + * @param handler The handler to invoke once the subscription request is + * complete. + */ +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler; + +/** + * Cancel all subscription requests as well as any requests to checkin. Note if + * there are subscription requests waiting on checkin to complete those requests + * would be marked as stale and be NO-OP's if they happen in the future. + * + * Also note this is a one time operation, you should only call this if you want + * to immediately stop all requests and deallocate the registrar. After calling + * this once you would no longer be able to use this registrar object. + */ +- (void)cancelAllRequests; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.m new file mode 100644 index 0000000..47a22ec --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.m @@ -0,0 +1,108 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRegistrar.h" + +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPubSubRegistrar.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +@interface FIRMessagingRegistrar () + +@property(nonatomic, readwrite, assign) BOOL stopAllSubscriptions; + +@property(nonatomic, readwrite, strong) FIRMessagingCheckinService *checkinService; +@property(nonatomic, readwrite, strong) FIRMessagingPubSubRegistrar *pubsubRegistrar; + +@end + +@implementation FIRMessagingRegistrar + +- (NSString *)deviceAuthID { + return self.checkinService.deviceAuthID; +} + +- (NSString *)secretToken { + return self.checkinService.secretToken; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _checkinService = [[FIRMessagingCheckinService alloc] init]; + // TODO(chliangGoogle): Merge pubsubRegistrar with Registrar as it is hard to track how many + // checkinService instances by separating classes too often. + _pubsubRegistrar = [[FIRMessagingPubSubRegistrar alloc] initWithCheckinService:_checkinService]; + } + return self; +} + +#pragma mark - Checkin + +- (BOOL)tryToLoadValidCheckinInfo { + [self.checkinService tryToLoadPrefetchedCheckinPreferences]; + return [self.checkinService hasValidCheckinInfo]; +} + +#pragma mark - Subscribe/Unsubscribe + +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler { + _FIRMessagingDevAssert(handler, @"Invalid nil handler"); + + if ([self tryToLoadValidCheckinInfo]) { + [self doUpdateSubscriptionForTopic:topic + token:token + options:options + shouldDelete:shouldDelete + completion:handler]; + + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRegistrar000, + @"Device check in error, no auth credentials found"); + NSError *error = [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeMissingDeviceID]; + handler(error); + } +} + +- (void)cancelAllRequests { + self.stopAllSubscriptions = YES; + [self.pubsubRegistrar stopAllSubscriptionRequests]; +} + +#pragma mark - Private + +- (void)doUpdateSubscriptionForTopic:(NSString *)topic + token:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + completion:(FIRMessagingTopicOperationCompletion)completion { + _FIRMessagingDevAssert([self.checkinService hasValidCheckinInfo], + @"No valid checkin info found before subscribe"); + + [self.pubsubRegistrar updateSubscriptionToTopic:topic + withToken:token + options:options + shouldDelete:shouldDelete + handler:completion]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h new file mode 100644 index 0000000..f0010b3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Swizzle remote-notification callbacks to invoke FIRMessaging methods + * before calling original implementations. + */ +@interface FIRMessagingRemoteNotificationsProxy : NSObject + +/** + * Checks the `FirebaseAppDelegateProxyEnabled` key in the App's Info.plist. If the key is + * missing or incorrectly formatted, returns `YES`. + * + * @return YES if the Application Delegate and User Notification Center methods can be swizzled. + * Otherwise, returns NO. + */ ++ (BOOL)canSwizzleMethods; + +/** + * A shared instance of `FIRMessagingRemoteNotificationsProxy` + */ ++ (instancetype)sharedProxy; + +/** + * Swizzles Application Delegate's remote-notification callbacks and User Notification Center + * delegate callback, and invokes the original selectors once done. + */ +- (void)swizzleMethodsIfPossible; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m new file mode 100644 index 0000000..e3a137f --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m @@ -0,0 +1,602 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRemoteNotificationsProxy.h" + +#import +#import + +#import "FIRMessagingConstants.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessaging_Private.h" +#import + +static void * UserNotificationObserverContext = &UserNotificationObserverContext; + +static NSString *kUserNotificationWillPresentSelectorString = + @"userNotificationCenter:willPresentNotification:withCompletionHandler:"; +static NSString *kUserNotificationDidReceiveResponseSelectorString = + @"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:"; + +@interface FIRMessagingRemoteNotificationsProxy () + +@property(strong, nonatomic) NSMutableDictionary *originalAppDelegateImps; +@property(strong, nonatomic) NSMutableDictionary *swizzledSelectorsByClass; + +@property(nonatomic) BOOL didSwizzleMethods; + +@property(nonatomic) BOOL hasSwizzledUserNotificationDelegate; +@property(nonatomic) BOOL isObservingUserNotificationDelegateChanges; + +@property(strong, nonatomic) id userNotificationCenter; +@property(strong, nonatomic) id currentUserNotificationCenterDelegate; + +@property(strong, nonatomic) GULAppDelegateInterceptorID appDelegateInterceptorID; + +@end + +@implementation FIRMessagingRemoteNotificationsProxy + ++ (BOOL)canSwizzleMethods { + return [GULAppDelegateSwizzler isAppDelegateProxyEnabled]; +} + ++ (instancetype)sharedProxy { + static FIRMessagingRemoteNotificationsProxy *proxy; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + proxy = [[FIRMessagingRemoteNotificationsProxy alloc] init]; + }); + return proxy; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _originalAppDelegateImps = [[NSMutableDictionary alloc] init]; + _swizzledSelectorsByClass = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)dealloc { + [self unswizzleAllMethods]; + self.swizzledSelectorsByClass = nil; + [self.originalAppDelegateImps removeAllObjects]; + self.originalAppDelegateImps = nil; + [self removeUserNotificationCenterDelegateObserver]; +} + +- (void)swizzleMethodsIfPossible { + // Already swizzled. + if (self.didSwizzleMethods) { + return; + } + + [GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods]; + self.appDelegateInterceptorID = [GULAppDelegateSwizzler registerAppDelegateInterceptor:self]; + + // Add KVO listener on [UNUserNotificationCenter currentNotificationCenter]'s delegate property + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + if (notificationCenterClass) { + // We are linked against iOS 10 SDK or above + id notificationCenter = getNamedPropertyFromObject(notificationCenterClass, + @"currentNotificationCenter", + notificationCenterClass); + if (notificationCenter) { + [self listenForDelegateChangesInUserNotificationCenter:notificationCenter]; + } + } + + self.didSwizzleMethods = YES; +} + +- (void)unswizzleAllMethods { + if (self.appDelegateInterceptorID) { + [GULAppDelegateSwizzler unregisterAppDelegateInterceptorWithID:self.appDelegateInterceptorID]; + } + + for (NSString *className in self.swizzledSelectorsByClass) { + Class klass = NSClassFromString(className); + NSArray *selectorStrings = self.swizzledSelectorsByClass[className]; + for (NSString *selectorString in selectorStrings) { + SEL selector = NSSelectorFromString(selectorString); + [self unswizzleSelector:selector inClass:klass]; + } + } + [self.swizzledSelectorsByClass removeAllObjects]; +} + +- (void)listenForDelegateChangesInUserNotificationCenter:(id)notificationCenter { + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + if (![notificationCenter isKindOfClass:notificationCenterClass]) { + return; + } + id delegate = getNamedPropertyFromObject(notificationCenter, @"delegate", nil); + Protocol *delegateProtocol = NSProtocolFromString(@"UNUserNotificationCenterDelegate"); + if ([delegate conformsToProtocol:delegateProtocol]) { + // Swizzle this object now, if available + [self swizzleUserNotificationCenterDelegate:delegate]; + } + // Add KVO observer for "delegate" keyPath for future changes + [self addDelegateObserverToUserNotificationCenter:notificationCenter]; +} + +#pragma mark - UNNotificationCenter Swizzling + +- (void)swizzleUserNotificationCenterDelegate:(id _Nonnull)delegate { + if (self.currentUserNotificationCenterDelegate == delegate) { + // Via pointer-check, compare if we have already swizzled this item. + return; + } + Protocol *userNotificationCenterProtocol = + NSProtocolFromString(@"UNUserNotificationCenterDelegate"); + if ([delegate conformsToProtocol:userNotificationCenterProtocol]) { + SEL willPresentNotificationSelector = + NSSelectorFromString(kUserNotificationWillPresentSelectorString); + // Swizzle the optional method + // "userNotificationCenter:willPresentNotification:withCompletionHandler:", if it is + // implemented. Do not swizzle otherwise, as an implementation *will* be created, which will + // fool iOS into thinking that this method is implemented, and therefore not send notifications + // to the fallback method in the app delegate + // "application:didReceiveRemoteNotification:fetchCompletionHandler:". + if ([delegate respondsToSelector:willPresentNotificationSelector]) { + [self swizzleSelector:willPresentNotificationSelector + inClass:[delegate class] + withImplementation:(IMP)FCM_swizzle_willPresentNotificationWithHandler + inProtocol:userNotificationCenterProtocol]; + } + SEL didReceiveNotificationResponseSelector = + NSSelectorFromString(kUserNotificationDidReceiveResponseSelectorString); + if ([delegate respondsToSelector:didReceiveNotificationResponseSelector]) { + [self swizzleSelector:didReceiveNotificationResponseSelector + inClass:[delegate class] + withImplementation:(IMP)FCM_swizzle_didReceiveNotificationResponseWithHandler + inProtocol:userNotificationCenterProtocol]; + } + self.currentUserNotificationCenterDelegate = delegate; + self.hasSwizzledUserNotificationDelegate = YES; + } +} + +- (void)unswizzleUserNotificationCenterDelegate:(id _Nonnull)delegate { + if (self.currentUserNotificationCenterDelegate != delegate) { + // We aren't swizzling this delegate, so don't do anything. + return; + } + SEL willPresentNotificationSelector = + NSSelectorFromString(kUserNotificationWillPresentSelectorString); + // Call unswizzle methods, even if the method was not implemented (it will fail gracefully). + [self unswizzleSelector:willPresentNotificationSelector + inClass:[self.currentUserNotificationCenterDelegate class]]; + SEL didReceiveNotificationResponseSelector = + NSSelectorFromString(kUserNotificationDidReceiveResponseSelectorString); + [self unswizzleSelector:didReceiveNotificationResponseSelector + inClass:[self.currentUserNotificationCenterDelegate class]]; + self.currentUserNotificationCenterDelegate = nil; + self.hasSwizzledUserNotificationDelegate = NO; +} + +#pragma mark - KVO for UNUserNotificationCenter + +- (void)addDelegateObserverToUserNotificationCenter:(id)userNotificationCenter { + [self removeUserNotificationCenterDelegateObserver]; + @try { + [userNotificationCenter addObserver:self + forKeyPath:NSStringFromSelector(@selector(delegate)) + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:UserNotificationObserverContext]; + self.userNotificationCenter = userNotificationCenter; + self.isObservingUserNotificationDelegateChanges = YES; + } @catch (NSException *exception) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxy000, + @"Encountered exception trying to add a KVO observer for " + @"UNUserNotificationCenter's 'delegate' property: %@", + exception); + } @finally { + + } +} + +- (void)removeUserNotificationCenterDelegateObserver { + if (!self.userNotificationCenter) { + return; + } + @try { + [self.userNotificationCenter removeObserver:self + forKeyPath:NSStringFromSelector(@selector(delegate)) + context:UserNotificationObserverContext]; + self.userNotificationCenter = nil; + self.isObservingUserNotificationDelegateChanges = NO; + } @catch (NSException *exception) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxy001, + @"Encountered exception trying to remove a KVO observer for " + @"UNUserNotificationCenter's 'delegate' property: %@", + exception); + } @finally { + + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if (context == UserNotificationObserverContext) { + if ([keyPath isEqualToString:NSStringFromSelector(@selector(delegate))]) { + id oldDelegate = change[NSKeyValueChangeOldKey]; + if (oldDelegate && oldDelegate != [NSNull null]) { + [self unswizzleUserNotificationCenterDelegate:oldDelegate]; + } + id newDelegate = change[NSKeyValueChangeNewKey]; + if (newDelegate && newDelegate != [NSNull null]) { + [self swizzleUserNotificationCenterDelegate:newDelegate]; + } + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +#pragma mark - NSProxy methods + +- (void)saveOriginalImplementation:(IMP)imp forSelector:(SEL)selector { + if (imp && selector) { + NSValue *IMPValue = [NSValue valueWithPointer:imp]; + NSString *selectorString = NSStringFromSelector(selector); + self.originalAppDelegateImps[selectorString] = IMPValue; + } +} + +- (IMP)originalImplementationForSelector:(SEL)selector { + NSString *selectorString = NSStringFromSelector(selector); + NSValue *implementation_value = self.originalAppDelegateImps[selectorString]; + if (!implementation_value) { + return nil; + } + + IMP imp; + [implementation_value getValue:&imp]; + return imp; +} + +- (void)trackSwizzledSelector:(SEL)selector ofClass:(Class)klass { + NSString *className = NSStringFromClass(klass); + NSString *selectorString = NSStringFromSelector(selector); + NSArray *selectors = self.swizzledSelectorsByClass[selectorString]; + if (selectors) { + selectors = [selectors arrayByAddingObject:selectorString]; + } else { + selectors = @[selectorString]; + } + self.swizzledSelectorsByClass[className] = selectors; +} + +- (void)removeImplementationForSelector:(SEL)selector { + NSString *selectorString = NSStringFromSelector(selector); + [self.originalAppDelegateImps removeObjectForKey:selectorString]; +} + +- (void)swizzleSelector:(SEL)originalSelector + inClass:(Class)klass + withImplementation:(IMP)swizzledImplementation + inProtocol:(Protocol *)protocol { + Method originalMethod = class_getInstanceMethod(klass, originalSelector); + + if (originalMethod) { + // This class implements this method, so replace the original implementation + // with our new implementation and save the old implementation. + + IMP __original_method_implementation = + method_setImplementation(originalMethod, swizzledImplementation); + + IMP __nonexistant_method_implementation = [self nonExistantMethodImplementationForClass:klass]; + + if (__original_method_implementation && + __original_method_implementation != __nonexistant_method_implementation && + __original_method_implementation != swizzledImplementation) { + [self saveOriginalImplementation:__original_method_implementation + forSelector:originalSelector]; + } + } else { + // The class doesn't have this method, so add our swizzled implementation as the + // original implementation of the original method. + struct objc_method_description method_description = + protocol_getMethodDescription(protocol, originalSelector, NO, YES); + + BOOL methodAdded = class_addMethod(klass, + originalSelector, + swizzledImplementation, + method_description.types); + if (!methodAdded) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxyMethodNotAdded, + @"Could not add method for %@ to class %@", + NSStringFromSelector(originalSelector), + NSStringFromClass(klass)); + } + } + [self trackSwizzledSelector:originalSelector ofClass:klass]; +} + +- (void)unswizzleSelector:(SEL)selector inClass:(Class)klass { + + Method swizzledMethod = class_getInstanceMethod(klass, selector); + if (!swizzledMethod) { + // This class doesn't seem to have this selector as an instance method? Bail out. + return; + } + + IMP original_imp = [self originalImplementationForSelector:selector]; + if (original_imp) { + // Restore the original implementation as the current implementation + method_setImplementation(swizzledMethod, original_imp); + [self removeImplementationForSelector:selector]; + } else { + // This class originally did not have an implementation for this selector. + + // We can't actually remove methods in Objective C 2.0, but we could set + // its method to something non-existent. This should give us the same + // behavior as if the method was not implemented. + // See: http://stackoverflow.com/a/8276527/9849 + + IMP nonExistantMethodImplementation = [self nonExistantMethodImplementationForClass:klass]; + method_setImplementation(swizzledMethod, nonExistantMethodImplementation); + } +} + +#pragma mark - Reflection Helpers + +// This is useful to generate from a stable, "known missing" selector, as the IMP can be compared +// in case we are setting an implementation for a class that was previously "unswizzled" into a +// non-existant implementation. +- (IMP)nonExistantMethodImplementationForClass:(Class)klass { + SEL nonExistantSelector = NSSelectorFromString(@"aNonExistantMethod"); + IMP nonExistantMethodImplementation = class_getMethodImplementation(klass, nonExistantSelector); + return nonExistantMethodImplementation; +} + +// A safe, non-leaky way return a property object by its name +id getNamedPropertyFromObject(id object, NSString *propertyName, Class klass) { + SEL selector = NSSelectorFromString(propertyName); + if (![object respondsToSelector:selector]) { + return nil; + } + if (!klass) { + klass = [NSObject class]; + } + // Suppress clang warning about leaks in performSelector + // The alternative way to perform this is to invoke + // the method as a block (see http://stackoverflow.com/a/20058585), + // but this approach sometimes returns incomplete objects. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id property = [object performSelector:selector]; +#pragma clang diagnostic pop + if (![property isKindOfClass:klass]) { + return nil; + } + return property; +} + +#pragma mark - UIApplicationDelegate + +#if TARGET_OS_IOS +- (void)application:(UIApplication *)application +didReceiveRemoteNotification:(NSDictionary *)userInfo { + [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; +} +#endif // TARGET_OS_IOS + +- (void)application:(UIApplication *)application +didReceiveRemoteNotification:(NSDictionary *)userInfo +fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; +} + +- (void)application:(UIApplication *)application +didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + // Pass the APNSToken along to FIRMessaging (and auto-detect the token type) + [FIRMessaging messaging].APNSToken = deviceToken; +} + +- (void)application:(UIApplication *)application +didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + // Log the fact that we failed to register for remote notifications + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxyAPNSFailed, + @"Error in " + @"application:didFailToRegisterForRemoteNotificationsWithError: %@", + error.localizedDescription); +} + +#pragma mark - Swizzled Methods + +/** + * Swizzle the notification handler for iOS 10+ devices. + * Signature of original handler is as below: + * - (void)userNotificationCenter:(UNUserNotificationCenter *)center + * willPresentNotification:(UNNotification *)notification + * withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler + * In order to make FCM SDK compile and compatible with iOS SDKs before iOS 10, hide the + * parameter types from the swizzling implementation. + */ +void FCM_swizzle_willPresentNotificationWithHandler( + id self, SEL _cmd, id center, id notification, void (^handler)(NSUInteger)) { + + FIRMessagingRemoteNotificationsProxy *proxy = [FIRMessagingRemoteNotificationsProxy sharedProxy]; + IMP original_imp = [proxy originalImplementationForSelector:_cmd]; + + void (^callOriginalMethodIfAvailable)(void) = ^{ + if (original_imp) { + ((void (*)(id, SEL, id, id, void (^)(NSUInteger)))original_imp)( + self, _cmd, center, notification, handler); + } + return; + }; + + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + Class notificationClass = NSClassFromString(@"UNNotification"); + if (!notificationCenterClass || !notificationClass) { + // Can't find UserNotifications framework. Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + } + + if (!center || ![center isKindOfClass:[notificationCenterClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!notification || ![notification isKindOfClass:[notificationClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!handler) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + // Attempt to access the user info + id notificationUserInfo = userInfoFromNotification(notification); + + if (!notificationUserInfo) { + // Could not access notification.request.content.userInfo. + callOriginalMethodIfAvailable(); + return; + } + + [[FIRMessaging messaging] appDidReceiveMessage:notificationUserInfo]; + // Execute the original implementation. + callOriginalMethodIfAvailable(); +} + +/** + * Swizzle the notification handler for iOS 10+ devices. + * Signature of original handler is as below: + * - (void)userNotificationCenter:(UNUserNotificationCenter *)center + * didReceiveNotificationResponse:(UNNotificationResponse *)response + * withCompletionHandler:(void (^)(void))completionHandler + * In order to make FCM SDK compile and compatible with iOS SDKs before iOS 10, hide the + * parameter types from the swizzling implementation. + */ +void FCM_swizzle_didReceiveNotificationResponseWithHandler( + id self, SEL _cmd, id center, id response, void (^handler)(void)) { + + FIRMessagingRemoteNotificationsProxy *proxy = [FIRMessagingRemoteNotificationsProxy sharedProxy]; + IMP original_imp = [proxy originalImplementationForSelector:_cmd]; + + void (^callOriginalMethodIfAvailable)(void) = ^{ + if (original_imp) { + ((void (*)(id, SEL, id, id, void (^)(void)))original_imp)( + self, _cmd, center, response, handler); + } + return; + }; + + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + Class responseClass = NSClassFromString(@"UNNotificationResponse"); + if (!center || ![center isKindOfClass:[notificationCenterClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!response || ![response isKindOfClass:[responseClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!handler) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + // Try to access the response.notification property + SEL notificationSelector = NSSelectorFromString(@"notification"); + if (![response respondsToSelector:notificationSelector]) { + // Cannot access the .notification property. + callOriginalMethodIfAvailable(); + return; + } + id notificationClass = NSClassFromString(@"UNNotification"); + id notification = getNamedPropertyFromObject(response, @"notification", notificationClass); + + // With a notification object, use the common code to reach deep into notification + // (notification.request.content.userInfo) + id notificationUserInfo = userInfoFromNotification(notification); + if (!notificationUserInfo) { + // Could not access notification.request.content.userInfo. + callOriginalMethodIfAvailable(); + return; + } + + [[FIRMessaging messaging] appDidReceiveMessage:notificationUserInfo]; + // Execute the original implementation. + callOriginalMethodIfAvailable(); +} + +id userInfoFromNotification(id notification) { + + // Select the userInfo field from UNNotification.request.content.userInfo. + SEL requestSelector = NSSelectorFromString(@"request"); + if (![notification respondsToSelector:requestSelector]) { + // Cannot access the request property. + return nil; + } + Class requestClass = NSClassFromString(@"UNNotificationRequest"); + id notificationRequest = getNamedPropertyFromObject(notification, @"request", requestClass); + + SEL notificationContentSelector = NSSelectorFromString(@"content"); + if (!notificationRequest + || ![notificationRequest respondsToSelector:notificationContentSelector]) { + // Cannot access the content property. + return nil; + } + Class contentClass = NSClassFromString(@"UNNotificationContent"); + id notificationContent = getNamedPropertyFromObject(notificationRequest, + @"content", + contentClass); + + SEL notificationUserInfoSelector = NSSelectorFromString(@"userInfo"); + if (!notificationContent + || ![notificationContent respondsToSelector:notificationUserInfoSelector]) { + // Cannot access the userInfo property. + return nil; + } + id notificationUserInfo = getNamedPropertyFromObject(notificationContent, + @"userInfo", + [NSDictionary class]); + + if (!notificationUserInfo) { + // This is not the expected notification handler. + return nil; + } + + return notificationUserInfo; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.h new file mode 100644 index 0000000..09f1d44 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.h @@ -0,0 +1,201 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRMessagingPersistentSyncMessage; + +// table data handlers +/** + * Handle message stored in the outgoing RMQ messages table. + * + * @param rmqId The rmqID of the message. + * @param tag The message tag. + * @param data The data stored in the message. + */ +typedef void(^FCMOutgoingRmqMessagesTableHandler)(int64_t rmqId, int8_t tag, NSData *data); + +/// Outgoing messages RMQ table +extern NSString *const kTableOutgoingRmqMessages; +/// Server to device RMQ table +extern NSString *const kTableS2DRmqIds; + +@interface FIRMessagingRmq2PersistentStore : NSObject + +/** + * Initialize and open the RMQ database on the client. + * + * @param databaseName The name for RMQ database. + * + * @return A store used to persist messages on the client. + */ +- (instancetype)initWithDatabaseName:(NSString *)databaseName; + +/** + * Save outgoing message in RMQ. + * + * @param rmqId The rmqID for the message. + * @param tag The tag of the message proto. + * @param data The data being sent in the message. + * @param error The error if any while saving the message to the persistent store. + * + * @return YES if the message was successfully saved to the persistent store else NO. + */ +- (BOOL)saveMessageWithRmqId:(int64_t)rmqId + tag:(int8_t)tag + data:(NSData *)data + error:(NSError **)error; + +/** + * Add unacked server to device message with a given rmqID to the persistent store. + * + * @param rmqId The rmqID of the message that was not acked by the cient. + * + * @return YES if the save was successful else NO. + */ +- (BOOL)saveUnackedS2dMessageWithRmqId:(NSString *)rmqId; + +/** + * Update the last RMQ ID that was sent by the client. + * + * @param rmqID The latest rmqID sent by the device. + * + * @return YES if the last rmqID was successfully saved else NO. + */ +- (BOOL)updateLastOutgoingRmqId:(int64_t)rmqID; + +#pragma mark - Query + +/** + * Query the highest rmqID saved in the Outgoing messages table. + * + * @return The highest rmqID amongst all the messages in the Outgoing RMQ table. If no message + * was ever persisted return 0. + */ +- (int64_t)queryHighestRmqId; + +/** + * The last rmqID that was saved on the client. + * + * @return The last rmqID that was saved. If no rmqID was ever persisted return 0. + */ +- (int64_t)queryLastRmqId; + +/** + * Get a list of all unacked server to device messages stored on the client. + * + * @return List of all unacked s2d messages in the persistent store. + */ +- (NSArray *)unackedS2dRmqIds; + +/** + * Iterate over all outgoing messages in the RMQ table. + * + * @param handler The handler invoked with each message in the outgoing RMQ table. + */ +- (void)scanOutgoingRmqMessagesWithHandler:(FCMOutgoingRmqMessagesTableHandler)handler; + +#pragma mark - Delete + +/** + * Delete messages with given rmqID's from a table. + * + * @param tableName The table name from which to delete the rmq messages. + * @param rmqIds The rmqID's of the messages to be deleted. + * + * @return The number of messages that were successfully deleted. + */ +- (int)deleteMessagesFromTable:(NSString *)tableName + withRmqIds:(NSArray *)rmqIds; + +/** + * Remove database from the device. + * + * @param dbName The database name to be deleted. + */ ++ (void)removeDatabase:(NSString *)dbName; + +#pragma mark - Sync Messages + +/** + * Save sync message to persistent store to check for duplicates. + * + * @param rmqID The rmqID of the message to save. + * @param expirationTime The expiration time of the message to save. + * @param apnsReceived YES if the message was received via APNS else NO. + * @param mcsReceived YES if the message was received via MCS else NO. + * @param error The error if any while saving the message to store. + * + * @return YES if the message was saved successfully else NO. + */ +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError **)error; + +/** + * Update sync message received via APNS. + * + * @param rmqID The rmqID of the sync message. + * @param error The error if any while updating the sync message in persistence. + * + * @return YES if the update was successful else NO. + */ +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID + error:(NSError **)error; + +/** + * Update sync message received via MCS. + * + * @param rmqID The rmqID of the sync message. + * @param error The error if any while updating the sync message in persistence. + * + * @return YES if the update was successful else NO. + */ +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID + error:(NSError **)error; + +/** + * Query sync message table for a given rmqID. + * + * @param rmqID The rmqID to search for in SYNC_RMQ. + * + * @return The sync message that was persisted with `rmqID`. If no such message was persisted + * return nil. + */ +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete sync message with rmqID. + * + * @param rmqID The rmqID of the message to delete. + * + * @return YES if a sync message with rmqID was found and deleted successfully else NO. + */ +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete the expired sync messages from persisten store. Also deletes messages that have been + * delivered both via APNS and MCS. + * + * @param error The error if any while deleting the messages. + * + * @return The total number of messages that were deleted from the persistent store. + */ +- (int)deleteExpiredOrFinishedSyncMessages:(NSError **)error; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.m new file mode 100644 index 0000000..bef6aac --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.m @@ -0,0 +1,811 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRmq2PersistentStore.h" + +#import + +#import "FIRMessagingConstants.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPersistentSyncMessage.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" +#import "Protos/GtalkCore.pbobjc.h" + +#ifndef _FIRMessagingRmqLogAndExit +#define _FIRMessagingRmqLogAndExit(stmt, return_value) \ +do { \ +[self logErrorAndFinalizeStatement:stmt]; \ +return return_value; \ +} while(0) +#endif + +typedef enum : NSUInteger { + FIRMessagingRmqDirectoryUnknown, + FIRMessagingRmqDirectoryDocuments, + FIRMessagingRmqDirectoryApplicationSupport, +} FIRMessagingRmqDirectory; + +static NSString *const kFCMRmqStoreTag = @"FIRMessagingRmqStore:"; + +// table names +NSString *const kTableOutgoingRmqMessages = @"outgoingRmqMessages"; +NSString *const kTableLastRmqId = @"lastrmqid"; +NSString *const kOldTableS2DRmqIds = @"s2dRmqIds"; +NSString *const kTableS2DRmqIds = @"s2dRmqIds_1"; + +// Used to prevent de-duping of sync messages received both via APNS and MCS. +NSString *const kTableSyncMessages = @"incomingSyncMessages"; + +static NSString *const kTablePrefix = @""; + +// create tables +static NSString *const kCreateTableOutgoingRmqMessages = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id INTEGER, " + @"type INTEGER, " + @"ts INTEGER, " + @"data BLOB)"; + +static NSString *const kCreateTableLastRmqId = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id INTEGER)"; + +static NSString *const kCreateTableS2DRmqIds = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id TEXT)"; + +static NSString *const kCreateTableSyncMessages = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id TEXT, " + @"expiration_ts INTEGER, " + @"apns_recv INTEGER, " + @"mcs_recv INTEGER)"; + +static NSString *const kDropTableCommand = + @"drop TABLE if exists %@%@"; + +// table infos +static NSString *const kRmqIdColumn = @"rmq_id"; +static NSString *const kDataColumn = @"data"; +static NSString *const kProtobufTagColumn = @"type"; +static NSString *const kIdColumn = @"_id"; + +static NSString *const kOutgoingRmqMessagesColumns = @"rmq_id, type, data"; + +// Sync message columns +static NSString *const kSyncMessagesColumns = @"rmq_id, expiration_ts, apns_recv, mcs_recv"; +// Message time expiration in seconds since 1970 +static NSString *const kSyncMessageExpirationTimestampColumn = @"expiration_ts"; +static NSString *const kSyncMessageAPNSReceivedColumn = @"apns_recv"; +static NSString *const kSyncMessageMCSReceivedColumn = @"mcs_recv"; + +// table data handlers +typedef void(^FCMOutgoingRmqMessagesTableHandler)(int64_t rmqId, int8_t tag, NSData *data); + +// Utility to create an NSString from a sqlite3 result code +NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + const char *errorStr = sqlite3_errstr(result); +#pragma pop + NSString *errorString = [NSString stringWithFormat:@"%d - %s", result, errorStr]; + return errorString; +} + +@interface FIRMessagingRmq2PersistentStore () { + sqlite3 *_database; +} + +@property(nonatomic, readwrite, strong) NSString *databaseName; +@property(nonatomic, readwrite, assign) FIRMessagingRmqDirectory currentDirectory; + +@end + +@implementation FIRMessagingRmq2PersistentStore + +- (instancetype)initWithDatabaseName:(NSString *)databaseName { + self = [super init]; + if (self) { + _databaseName = [databaseName copy]; +#if TARGET_OS_IOS + BOOL didMoveToApplicationSupport = + [self moveToApplicationSupportSubDirectory:kFIRMessagingSubDirectoryName]; + + _currentDirectory = didMoveToApplicationSupport + ? FIRMessagingRmqDirectoryApplicationSupport + : FIRMessagingRmqDirectoryDocuments; +#else + _currentDirectory = FIRMessagingRmqDirectoryApplicationSupport; +#endif + + [self openDatabase:_databaseName]; + } + return self; +} + +- (void)dealloc { + sqlite3_close(_database); +} + +- (BOOL)moveToApplicationSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), + NSUserDomainMask, YES); + NSString *applicationSupportDirPath = directoryPaths.lastObject; + NSArray *components = @[applicationSupportDirPath, subDirectoryName]; + NSString *subDirectoryPath = [NSString pathWithComponents:components]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + // Cannot move to non-existent directory + return NO; + } + + if ([self doesFileExistInDirectory:FIRMessagingRmqDirectoryDocuments]) { + NSString *oldPlistPath = [[self class] pathForDatabase:self.databaseName + inDirectory:FIRMessagingRmqDirectoryDocuments]; + NSString *newPlistPath = [[self class] + pathForDatabase:self.databaseName + inDirectory:FIRMessagingRmqDirectoryApplicationSupport]; + + if ([self doesFileExistInDirectory:FIRMessagingRmqDirectoryApplicationSupport]) { + // File exists in both Documents and ApplicationSupport, delete the one in Documents + NSError *deleteError; + if (![[NSFileManager defaultManager] removeItemAtPath:oldPlistPath error:&deleteError]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore000, + @"Failed to delete old copy of %@.sqlite in Documents %@", + self.databaseName, deleteError); + } + return NO; + } + NSError *moveError; + if (![[NSFileManager defaultManager] moveItemAtPath:oldPlistPath + toPath:newPlistPath + error:&moveError]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore001, + @"Failed to move file %@ from %@ to %@. Error: %@", self.databaseName, + oldPlistPath, newPlistPath, moveError); + return NO; + } + } + // We moved the file if it existed, otherwise we didn't need to do anything + return YES; +} + +- (BOOL)doesFileExistInDirectory:(FIRMessagingRmqDirectory)directory { + NSString *path = [[self class] pathForDatabase:self.databaseName inDirectory:directory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + ++ (NSString *)pathForDatabase:(NSString *)dbName inDirectory:(FIRMessagingRmqDirectory)directory { + NSArray *paths; + NSArray *components; + NSString *dbNameWithExtension = [NSString stringWithFormat:@"%@.sqlite", dbName]; + NSString *errorMessage; + + switch (directory) { + case FIRMessagingRmqDirectoryDocuments: + paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + components = @[paths.lastObject, dbNameWithExtension]; + break; + + case FIRMessagingRmqDirectoryApplicationSupport: + paths = NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), + NSUserDomainMask, + YES); + components = @[ + paths.lastObject, + kFIRMessagingSubDirectoryName, + dbNameWithExtension + ]; + break; + + default: + errorMessage = [NSString stringWithFormat:@"Invalid directory type %lu", + (unsigned long)directory]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreInvalidRmqDirectory, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + break; + } + + return [NSString pathWithComponents:components]; +} + +- (void)createTableWithName:(NSString *)tableName command:(NSString *)command { + char *error; + NSString *createDatabase = [NSString stringWithFormat:command, kTablePrefix, tableName]; + if (sqlite3_exec(_database, [createDatabase UTF8String], NULL, NULL, &error) != SQLITE_OK) { + // remove db before failing + [self removeDatabase]; + NSString *errorMessage = [NSString stringWithFormat:@"Couldn't create table: %@ %@", + kCreateTableOutgoingRmqMessages, + [NSString stringWithCString:error encoding:NSUTF8StringEncoding]]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingTable, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + } +} + +- (void)dropTableWithName:(NSString *)tableName { + char *error; + NSString *dropTableSQL = [NSString stringWithFormat:kDropTableCommand, kTablePrefix, tableName]; + if (sqlite3_exec(_database, [dropTableSQL UTF8String], NULL, NULL, &error) != SQLITE_OK) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore002, + @"Failed to remove table %@", tableName); + } +} + +- (void)removeDatabase { + NSString *path = [[self class] pathForDatabase:self.databaseName + inDirectory:self.currentDirectory]; + [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; +} + ++ (void)removeDatabase:(NSString *)dbName { + NSString *documentsDirPath = [self pathForDatabase:dbName + inDirectory:FIRMessagingRmqDirectoryDocuments]; + NSString *standardDirPath = + [self pathForDatabase:dbName inDirectory:FIRMessagingRmqDirectoryApplicationSupport]; + [[NSFileManager defaultManager] removeItemAtPath:documentsDirPath error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:standardDirPath error:nil]; +} + +- (void)openDatabase:(NSString *)dbName { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *path = [[self class] pathForDatabase:dbName inDirectory:self.currentDirectory]; + + BOOL didOpenDatabase = YES; + if (![fileManager fileExistsAtPath:path]) { + // We've to separate between different versions here because of backwards compatbility issues. + int result = sqlite3_open([path UTF8String], &_database); + if (result != SQLITE_OK) { + NSString *errorString = FIRMessagingStringFromSQLiteResult(result); + NSString *errorMessage = + [NSString stringWithFormat:@"Could not open existing RMQ database at path %@, error: %@", + path, + errorString]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + return; + } + [self createTableWithName:kTableOutgoingRmqMessages + command:kCreateTableOutgoingRmqMessages]; + + [self createTableWithName:kTableLastRmqId command:kCreateTableLastRmqId]; + [self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds]; + } else { + // Calling sqlite3_open should create the database, since the file doesn't exist. + int result = sqlite3_open([path UTF8String], &_database); + if (result != SQLITE_OK) { + NSString *errorString = FIRMessagingStringFromSQLiteResult(result); + NSString *errorMessage = + [NSString stringWithFormat:@"Could not create RMQ database at path %@, error: %@", + path, + errorString]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingDatabase, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + didOpenDatabase = NO; + } else { + [self updateDbWithStringRmqID]; + } + } + + if (didOpenDatabase) { + [self createTableWithName:kTableSyncMessages command:kCreateTableSyncMessages]; + } +} + +- (void)updateDbWithStringRmqID { + [self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds]; + [self dropTableWithName:kOldTableS2DRmqIds]; +} + +#pragma mark - Insert + +- (BOOL)saveUnackedS2dMessageWithRmqId:(NSString *)rmqId { + NSString *insertFormat = @"INSERT INTO %@ (%@) VALUES (?)"; + NSString *insertSQL = [NSString stringWithFormat:insertFormat, + kTableS2DRmqIds, + kRmqIdColumn]; + sqlite3_stmt *insert_statement; + if (sqlite3_prepare_v2(_database, [insertSQL UTF8String], -1, &insert_statement, NULL) + != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_text(insert_statement, + 1, + [rmqId UTF8String], + (int)[rmqId length], + SQLITE_STATIC) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_step(insert_statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + sqlite3_finalize(insert_statement); + return YES; +} + +- (BOOL)saveMessageWithRmqId:(int64_t)rmqId + tag:(int8_t)tag + data:(NSData *)data + error:(NSError **)error { + NSString *insertFormat = @"INSERT INTO %@ (%@, %@, %@) VALUES (?, ?, ?)"; + NSString *insertSQL = [NSString stringWithFormat:insertFormat, + kTableOutgoingRmqMessages, // table + kRmqIdColumn, kProtobufTagColumn, kDataColumn /* columns */]; + sqlite3_stmt *insert_statement; + if (sqlite3_prepare_v2(_database, [insertSQL UTF8String], -1, &insert_statement, NULL) + != SQLITE_OK) { + if (error) { + *error = [NSError errorWithDomain:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_database)] + code:sqlite3_errcode(_database) + userInfo:nil]; + } + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_int64(insert_statement, 1, rmqId) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_int(insert_statement, 2, tag) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_blob(insert_statement, 3, [data bytes], (int)[data length], NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_step(insert_statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + + sqlite3_finalize(insert_statement); + return YES; +} + +- (int)deleteMessagesFromTable:(NSString *)tableName + withRmqIds:(NSArray *)rmqIds { + _FIRMessagingDevAssert([tableName isEqualToString:kTableOutgoingRmqMessages] || + [tableName isEqualToString:kTableLastRmqId] || + [tableName isEqualToString:kTableS2DRmqIds] || + [tableName isEqualToString:kTableSyncMessages], + @"%@: Invalid Table Name %@", kFCMRmqStoreTag, tableName); + + BOOL isRmqIDString = NO; + // RmqID is a string only for outgoing messages + if ([tableName isEqualToString:kTableS2DRmqIds] || + [tableName isEqualToString:kTableSyncMessages]) { + isRmqIDString = YES; + } + + NSMutableString *delete = [NSMutableString stringWithFormat:@"DELETE FROM %@ WHERE ", tableName]; + + NSString *toDeleteArgument = [NSString stringWithFormat:@"%@ = ? OR ", kRmqIdColumn]; + + int toDelete = (int)[rmqIds count]; + if (toDelete == 0) { + return 0; + } + int maxBatchSize = 100; + int start = 0; + int deleteCount = 0; + while (start < toDelete) { + + // construct the WHERE argument + int end = MIN(start + maxBatchSize, toDelete); + NSMutableString *whereArgument = [NSMutableString string]; + for (int i = start; i < end; i++) { + [whereArgument appendString:toDeleteArgument]; + } + // remove the last * OR * from argument + NSRange range = NSMakeRange([whereArgument length] -4, 4); + [whereArgument deleteCharactersInRange:range]; + NSString *deleteQuery = [NSString stringWithFormat:@"%@ %@", delete, whereArgument]; + + + // sqlite update + sqlite3_stmt *delete_statement; + if (sqlite3_prepare_v2(_database, [deleteQuery UTF8String], + -1, &delete_statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(delete_statement, 0); + } + + // bind values + int rmqIndex = 0; + int placeholderIndex = 1; // placeholders in sqlite3 start with 1 + for (NSString *rmqId in rmqIds) { // objectAtIndex: is O(n) -- would make it slow + if (rmqIndex < start) { + rmqIndex++; + continue; + } else if (rmqIndex >= end) { + break; + } else { + if (isRmqIDString) { + if (sqlite3_bind_text(delete_statement, + placeholderIndex, + [rmqId UTF8String], + (int)[rmqId length], + SQLITE_STATIC) != SQLITE_OK) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore003, + @"Failed to bind rmqID %@", rmqId); + continue; + } + } else { + int64_t rmqIdValue = [rmqId longLongValue]; + sqlite3_bind_int64(delete_statement, placeholderIndex, rmqIdValue); + } + placeholderIndex++; + } + rmqIndex++; + } + if (sqlite3_step(delete_statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(delete_statement, deleteCount); + } + sqlite3_finalize(delete_statement); + deleteCount += sqlite3_changes(_database); + start = end; + } + + // if we are here all of our sqlite queries should have succeeded + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore004, + @"%@ Trying to delete %d s2D ID's, successfully deleted %d", + kFCMRmqStoreTag, toDelete, deleteCount); + return deleteCount; +} + +#pragma mark - Query + +- (int64_t)queryHighestRmqId { + NSString *queryFormat = @"SELECT %@ FROM %@ ORDER BY %@ DESC LIMIT %d"; + NSString *query = [NSString stringWithFormat:queryFormat, + kRmqIdColumn, // column + kTableOutgoingRmqMessages, // table + kRmqIdColumn, // order by column + 1]; // limit + + sqlite3_stmt *statement; + int64_t highestRmqId = 0; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, highestRmqId); + } + if (sqlite3_step(statement) == SQLITE_ROW) { + highestRmqId = sqlite3_column_int64(statement, 0); + } + sqlite3_finalize(statement); + return highestRmqId; +} + +- (int64_t)queryLastRmqId { + NSString *queryFormat = @"SELECT %@ FROM %@ ORDER BY %@ DESC LIMIT %d"; + NSString *query = [NSString stringWithFormat:queryFormat, + kRmqIdColumn, // column + kTableLastRmqId, // table + kRmqIdColumn, // order by column + 1]; // limit + + sqlite3_stmt *statement; + int64_t lastRmqId = 0; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, lastRmqId); + } + if (sqlite3_step(statement) == SQLITE_ROW) { + lastRmqId = sqlite3_column_int64(statement, 0); + } + sqlite3_finalize(statement); + return lastRmqId; +} + +- (BOOL)updateLastOutgoingRmqId:(int64_t)rmqID { + NSString *queryFormat = @"INSERT OR REPLACE INTO %@ (%@, %@) VALUES (?, ?)"; + NSString *query = [NSString stringWithFormat:queryFormat, + kTableLastRmqId, // table + kIdColumn, kRmqIdColumn]; // columns + sqlite3_stmt *statement; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + if (sqlite3_bind_int(statement, 1, 1) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + if (sqlite3_bind_int64(statement, 2, rmqID) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + if (sqlite3_step(statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + sqlite3_finalize(statement); + return YES; +} + +- (NSArray *)unackedS2dRmqIds { + NSString *queryFormat = @"SELECT %@ FROM %@ ORDER BY %@ ASC"; + NSString *query = [NSString stringWithFormat:queryFormat, + kRmqIdColumn, + kTableS2DRmqIds, + kRmqIdColumn]; + sqlite3_stmt *statement; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore005, + @"%@: Could not find s2d ids", kFCMRmqStoreTag); + _FIRMessagingRmqLogAndExit(statement, @[]); + } + NSMutableArray *rmqIDArray = [NSMutableArray array]; + while (sqlite3_step(statement) == SQLITE_ROW) { + const char *rmqID = (char *)sqlite3_column_text(statement, 0); + [rmqIDArray addObject:[NSString stringWithUTF8String:rmqID]]; + } + sqlite3_finalize(statement); + return rmqIDArray; +} + +#pragma mark - Scan + +- (void)scanOutgoingRmqMessagesWithHandler:(FCMOutgoingRmqMessagesTableHandler)handler { + static NSString *queryFormat = @"SELECT %@ FROM %@ WHERE %@ != 0 ORDER BY %@ ASC"; + NSString *query = [NSString stringWithFormat:queryFormat, + kOutgoingRmqMessagesColumns, // select (rmq_id, type, data) + kTableOutgoingRmqMessages, // from table + kRmqIdColumn, // where + kRmqIdColumn]; // order by + sqlite3_stmt *statement; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + [self logError]; + sqlite3_finalize(statement); + return; + } + // can query sqlite3 for this but this is fine + const int rmqIdColumnNumber = 0; + const int typeColumnNumber = 1; + const int dataColumnNumber = 2; + while (sqlite3_step(statement) == SQLITE_ROW) { + int64_t rmqId = sqlite3_column_int64(statement, rmqIdColumnNumber); + int8_t type = sqlite3_column_int(statement, typeColumnNumber); + const void *bytes = sqlite3_column_blob(statement, dataColumnNumber); + int length = sqlite3_column_bytes(statement, dataColumnNumber); + _FIRMessagingDevAssert(bytes != NULL, + @"%@ Message with no data being stored in Rmq", + kFCMRmqStoreTag); + NSData *data = [NSData dataWithBytes:bytes length:length]; + handler(rmqId, type, data); + } + sqlite3_finalize(statement); +} + +#pragma mark - Sync Messages + +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID { + _FIRMessagingDevAssert([rmqID length], @"Invalid rmqID key %@ to search in SYNC_RMQ", rmqID); + + NSString *queryFormat = @"SELECT %@ FROM %@ WHERE %@ = '%@'"; + NSString *query = [NSString stringWithFormat:queryFormat, + kSyncMessagesColumns, // SELECT (rmq_id, expiration_ts, apns_recv, mcs_recv) + kTableSyncMessages, // FROM sync_rmq + kRmqIdColumn, // WHERE rmq_id + rmqID]; + + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + [self logError]; + sqlite3_finalize(stmt); + return nil; + } + + const int rmqIDColumn = 0; + const int expirationTimestampColumn = 1; + const int apnsReceivedColumn = 2; + const int mcsReceivedColumn = 3; + + int count = 0; + FIRMessagingPersistentSyncMessage *persistentMessage; + + while (sqlite3_step(stmt) == SQLITE_ROW) { + NSString *rmqID = + [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, rmqIDColumn)]; + int64_t expirationTimestamp = sqlite3_column_int64(stmt, expirationTimestampColumn); + BOOL apnsReceived = sqlite3_column_int(stmt, apnsReceivedColumn); + BOOL mcsReceived = sqlite3_column_int(stmt, mcsReceivedColumn); + + // create a new persistent message + persistentMessage = + [[FIRMessagingPersistentSyncMessage alloc] initWithRMQID:rmqID expirationTime:expirationTimestamp]; + persistentMessage.apnsReceived = apnsReceived; + persistentMessage.mcsReceived = mcsReceived; + + count++; + } + sqlite3_finalize(stmt); + + _FIRMessagingDevAssert(count <= 1, @"Found multiple messages in %@ with same RMQ ID", kTableSyncMessages); + return persistentMessage; +} + +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID { + _FIRMessagingDevAssert([rmqID length], @"Invalid rmqID key %@ to delete in SYNC_RMQ", rmqID); + return [self deleteMessagesFromTable:kTableSyncMessages withRmqIds:@[rmqID]] > 0; +} + +- (int)deleteExpiredOrFinishedSyncMessages:(NSError *__autoreleasing *)error { + int64_t now = FIRMessagingCurrentTimestampInSeconds(); + NSString *deleteSQL = @"DELETE FROM %@ " + @"WHERE %@ < %lld OR " // expirationTime < now + @"(%@ = 1 AND %@ = 1)"; // apns_received = 1 AND mcs_received = 1 + NSString *query = [NSString stringWithFormat:deleteSQL, + kTableSyncMessages, + kSyncMessageExpirationTimestampColumn, + now, + kSyncMessageAPNSReceivedColumn, + kSyncMessageMCSReceivedColumn]; + + NSString *errorReason = @"Failed to save delete expired sync messages from store."; + + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : errorReason }]; + } + _FIRMessagingRmqLogAndExit(stmt, 0); + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : errorReason }]; + } + _FIRMessagingRmqLogAndExit(stmt, 0); + } + + sqlite3_finalize(stmt); + int deleteCount = sqlite3_changes(_database); + return deleteCount; +} + +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError **)error { + _FIRMessagingDevAssert([rmqID length], @"Invalid nil message to persist to SYNC_RMQ"); + + NSString *insertFormat = @"INSERT INTO %@ (%@, %@, %@, %@) VALUES (?, ?, ?, ?)"; + NSString *insertSQL = [NSString stringWithFormat:insertFormat, + kTableSyncMessages, // Table name + kRmqIdColumn, // rmq_id + kSyncMessageExpirationTimestampColumn, // expiration_ts + kSyncMessageAPNSReceivedColumn, // apns_recv + kSyncMessageMCSReceivedColumn /* mcs_recv */]; + + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(_database, [insertSQL UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : @"Failed to save sync message to store." }]; + } + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_text(stmt, 1, [rmqID UTF8String], (int)[rmqID length], NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_int64(stmt, 2, expirationTime) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_int(stmt, 3, apnsReceived ? 1 : 0) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_int(stmt, 4, mcsReceived ? 1 : 0) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + sqlite3_finalize(stmt); + return YES; +} + +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID + error:(NSError **)error { + return [self updateSyncMessageWithRmqID:rmqID + column:kSyncMessageAPNSReceivedColumn + value:YES + error:error]; +} + +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID + error:(NSError *__autoreleasing *)error { + return [self updateSyncMessageWithRmqID:rmqID + column:kSyncMessageMCSReceivedColumn + value:YES + error:error]; +} + +- (BOOL)updateSyncMessageWithRmqID:(NSString *)rmqID + column:(NSString *)column + value:(BOOL)value + error:(NSError **)error { + _FIRMessagingDevAssert([column isEqualToString:kSyncMessageAPNSReceivedColumn] || + [column isEqualToString:kSyncMessageMCSReceivedColumn], + @"Invalid column name %@ for SYNC_RMQ", column); + NSString *queryFormat = @"UPDATE %@ " // Table name + @"SET %@ = %d " // column=value + @"WHERE %@ = ?"; // condition + NSString *query = [NSString stringWithFormat:queryFormat, + kTableSyncMessages, + column, + value ? 1 : 0, + kRmqIdColumn]; + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : @"Failed to update sync message"}]; + } + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_text(stmt, 1, [rmqID UTF8String], (int)[rmqID length], NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + sqlite3_finalize(stmt); + return YES; + +} + +#pragma mark - Private + +- (NSString *)lastErrorMessage { + return [NSString stringWithFormat:@"%s", sqlite3_errmsg(_database)]; +} + +- (int)lastErrorCode { + return sqlite3_errcode(_database); +} + +- (void)logError { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore006, + @"%@ error: code (%d) message: %@", kFCMRmqStoreTag, [self lastErrorCode], + [self lastErrorMessage]); +} + +- (void)logErrorAndFinalizeStatement:(sqlite3_stmt *)stmt { + [self logError]; + sqlite3_finalize(stmt); +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.h new file mode 100644 index 0000000..ba48b98 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.h @@ -0,0 +1,190 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GtalkDataMessageStanza; +@class GPBMessage; + +@class FIRMessagingPersistentSyncMessage; + +/** + * Called on each raw message. + */ +typedef void(^FIRMessagingRmqMessageHandler)(int64_t rmqId, int8_t tag, NSData *data); + +/** + * Called on each DataMessageStanza. + */ +typedef void(^FIRMessagingDataMessageHandler)(int64_t rmqId, GtalkDataMessageStanza *stanza); + +/** + * Used to scan through the rmq and perform actions on messages as required. + */ +@protocol FIRMessagingRmqScanner + +/** + * Scan the RMQ for outgoing messages and process them as required. + */ +- (void)scanWithRmqMessageHandler:(FIRMessagingRmqMessageHandler)rmqMessageHandler + dataMessageHandler:(FIRMessagingDataMessageHandler)dataMessageHandler; + +@end + +/** + * This manages the RMQ persistent store. + * + * The store is used to store all the S2D id's that were received by the client and were ACK'ed + * by us but the server hasn't confirmed the ACK. We don't delete these id's until the server + * ACK's us that they have received them. + * + * We also store the upstream messages(d2s) that were sent by the client. + * + * Also store the lastRMQId that was sent by us so that for a new connection being setup we don't + * duplicate RMQ Id's for the new messages. + */ +@interface FIRMessagingRmqManager : NSObject + +// designated initializer +- (instancetype)initWithDatabaseName:(NSString *)databaseName; + +- (void)loadRmqId; + +/** + * Save an upstream message to RMQ. If the message send fails for some reason we would not + * lose the message since it would be saved in the RMQ. + * + * @param message The upstream message to be saved. + * @param error The error if any while saving the message else nil. + * + * @return YES if the message was successfully saved to RMQ else NO. + */ +- (BOOL)saveRmqMessage:(GPBMessage *)message error:(NSError **)error; + +/** + * Save Server to device message with the given RMQ-ID. + * + * @param rmqID The rmqID of the s2d message to save. + * + * @return YES if the save was successfull else NO. + */ +- (BOOL)saveS2dMessageWithRmqId:(NSString *)rmqID; + +/** + * A list of all unacked Server to device RMQ IDs. + * + * @return A list of unacked Server to Device RMQ ID's. All values are Strings. + */ +- (NSArray *)unackedS2dRmqIds; + +/** + * Removes the outgoing message from RMQ store. + * + * @param rmqId The rmqID to remove from the store. + * + * @return The number of messages deleted successfully. + */ +- (int)removeRmqMessagesWithRmqId:(NSString *)rmqId; + +/** + * Removes the messages with the given rmqIDs from RMQ store. + * + * @param rmqIds The lsit of rmqID's to remove from the store. + * + * @return The number of messages deleted successfully. + */ +- (int)removeRmqMessagesWithRmqIds:(NSArray *)rmqIds; + +/** + * Removes a list of downstream messages from the RMQ. + * + * @param s2dIds The list of messages ACK'ed by the server that we should remove + * from the RMQ store. + */ +- (void)removeS2dIds:(NSArray *)s2dIds; + +#pragma mark - Sync Messages + +/** + * Get persisted sync message with rmqID. + * + * @param rmqID The rmqID of the persisted sync message. + * + * @return A valid persistent sync message with the given rmqID if found in the RMQ else nil. + */ +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete sync message with rmqID. + * + * @param rmqID The rmqID of the persisted sync message. + * + * @return YES if the message was successfully deleted else NO. + */ +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete the expired sync messages from persisten store. Also deletes messages that have been + * delivered both via APNS and MCS. + * + * @param error The error if any while deleting the messages. + * + * @return The total number of messages that were deleted from the persistent store. + */ +- (int)deleteExpiredOrFinishedSyncMessages:(NSError **)error; + +/** + * Save sync message received by the device. + * + * @param rmqID The rmqID of the message received. + * @param expirationTime The expiration time of the sync message received. + * @param apnsReceived YES if the message was received via APNS else NO. + * @param mcsReceived YES if the message was received via MCS else NO. + * @param error The error if any while saving the sync message to persistent store. + * + * @return YES if the message save was successful else NO. + */ +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError **)error; + +/** + * Update sync message received via APNS. + * + * @param rmqID The rmqID of the received message. + * @param error The error if any while updating the sync message. + * + * @return YES if the persistent sync message was successfully updated else NO. + */ +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID error:(NSError **)error; + +/** + * Update sync message received via MCS. + * + * @param rmqID The rmqID of the received message. + * @param error The error if any while updating the sync message. + * + * @return YES if the persistent sync message was successfully updated else NO. + */ +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID error:(NSError **)error; + +#pragma mark - Testing + ++ (void)removeDatabaseWithName:(NSString *)dbName; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.m new file mode 100644 index 0000000..449e3d6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.m @@ -0,0 +1,264 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRmqManager.h" + +#import + +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingRmq2PersistentStore.h" +#import "FIRMessagingUtilities.h" +#import "Protos/GtalkCore.pbobjc.h" + +#ifndef _FIRMessagingRmqLogAndExit +#define _FIRMessagingRmqLogAndExit(stmt, return_value) \ +do { \ + [self logErrorAndFinalizeStatement:stmt]; \ + return return_value; \ +} while(0) +#endif + +static NSString *const kFCMRmqTag = @"FIRMessagingRmq:"; + +@interface FIRMessagingRmqManager () + +@property(nonatomic, readwrite, strong) FIRMessagingRmq2PersistentStore *rmq2Store; +// map the category of an outgoing message with the number of messages for that category +// should always have two keys -- the app, gcm +@property(nonatomic, readwrite, strong) NSMutableDictionary *outstandingMessages; + +// Outgoing RMQ persistent id +@property(nonatomic, readwrite, assign) int64_t rmqId; + +@end + +@implementation FIRMessagingRmqManager + +- (instancetype)initWithDatabaseName:(NSString *)databaseName { + self = [super init]; + if (self) { + _FIRMessagingDevAssert([databaseName length] > 0, @"RMQ: Invalid rmq db name"); + _rmq2Store = [[FIRMessagingRmq2PersistentStore alloc] initWithDatabaseName:databaseName]; + _outstandingMessages = [NSMutableDictionary dictionaryWithCapacity:2]; + _rmqId = -1; + } + return self; +} + +- (void)loadRmqId { + if (self.rmqId >= 0) { + return; // already done + } + + [self loadInitialOutgoingPersistentId]; + if (self.outstandingMessages.count) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmqManager000, + @"%@: outstanding categories %ld", kFCMRmqTag, + _FIRMessaging_UL(self.outstandingMessages.count)); + } +} + +/** + * Initialize the 'initial RMQ': + * - max ID of any message in the queue + * - if the queue is empty, stored value in separate DB. + * + * Stream acks will remove from RMQ, when we remove the highest message we keep track + * of its ID. + */ +- (void)loadInitialOutgoingPersistentId { + + // we shouldn't always trust the lastRmqId stored in the LastRmqId table, because + // we only save to the LastRmqId table once in a while (after getting the lastRmqId sent + // by the server after reconnect, and after getting a rmq ack from the server). The + // rmq message with the highest rmq id tells the real story, so check against that first. + + int64_t rmqId = [self queryHighestRmqId]; + if (rmqId == 0) { + rmqId = [self querylastRmqId]; + } + self.rmqId = rmqId + 1; +} + +#pragma mark - Save + +/** + * Save a message to RMQ2. Will populate the rmq2 persistent ID. + */ +- (BOOL)saveRmqMessage:(GPBMessage *)message + error:(NSError **)error { + // send using rmq2manager + // the wire format of rmq2 id is a string. However, we keep it as a long internally + // in the database. So only convert the id to string when preparing for sending over + // the wire. + NSString *rmq2Id = FIRMessagingGetRmq2Id(message); + if (![rmq2Id length]) { + int64_t rmqId = [self nextRmqId]; + rmq2Id = [NSString stringWithFormat:@"%lld", rmqId]; + FIRMessagingSetRmq2Id(message, rmq2Id); + } + FIRMessagingProtoTag tag = FIRMessagingGetTagForProto(message); + return [self saveMessage:message withRmqId:[rmq2Id integerValue] tag:tag error:error]; +} + +- (BOOL)saveMessage:(GPBMessage *)message + withRmqId:(int64_t)rmqId + tag:(int8_t)tag + error:(NSError **)error { + NSData *data = [message data]; + return [self.rmq2Store saveMessageWithRmqId:rmqId tag:tag data:data error:error]; +} + +/** + * This is called when we delete the largest outgoing message from queue. + */ +- (void)saveLastOutgoingRmqId:(int64_t)rmqID { + [self.rmq2Store updateLastOutgoingRmqId:rmqID]; +} + +- (BOOL)saveS2dMessageWithRmqId:(NSString *)rmqID { + return [self.rmq2Store saveUnackedS2dMessageWithRmqId:rmqID]; +} + +#pragma mark - Query + +- (int64_t)queryHighestRmqId { + return [self.rmq2Store queryHighestRmqId]; +} + +- (int64_t)querylastRmqId { + return [self.rmq2Store queryLastRmqId]; +} + +- (NSArray *)unackedS2dRmqIds { + return [self.rmq2Store unackedS2dRmqIds]; +} + +#pragma mark - FIRMessagingRMQScanner protocol + +/** + * We don't have a 'getMessages' method - it would require loading in memory + * the entire content body of all messages. + * + * Instead we iterate and call 'resend' for each message. + * + * This is called: + * - on connect MCS, to resend any outstanding messages + * - init + */ +- (void)scanWithRmqMessageHandler:(FIRMessagingRmqMessageHandler)rmqMessageHandler + dataMessageHandler:(FIRMessagingDataMessageHandler)dataMessageHandler { + // no need to scan database with no callbacks + if (rmqMessageHandler || dataMessageHandler) { + [self.rmq2Store scanOutgoingRmqMessagesWithHandler:^(int64_t rmqId, int8_t tag, NSData *data) { + if (rmqMessageHandler != nil) { + rmqMessageHandler(rmqId, tag, data); + } + if (dataMessageHandler != nil && kFIRMessagingProtoTagDataMessageStanza == tag) { + GPBMessage *proto = + [FIRMessagingGetClassForTag((FIRMessagingProtoTag)tag) parseFromData:data error:NULL]; + GtalkDataMessageStanza *stanza = (GtalkDataMessageStanza *)proto; + dataMessageHandler(rmqId, stanza); + } + }]; + } +} + +#pragma mark - Remove + +- (void)ackReceivedForRmqId:(NSString *)rmqId { + // TODO: Optional book-keeping +} + +- (int)removeRmqMessagesWithRmqId:(NSString *)rmqId { + return [self removeRmqMessagesWithRmqIds:@[rmqId]]; +} + +- (int)removeRmqMessagesWithRmqIds:(NSArray *)rmqIds { + if (![rmqIds count]) { + return 0; + } + for (NSString *rmqId in rmqIds) { + [self ackReceivedForRmqId:rmqId]; + } + int64_t maxRmqId = -1; + for (NSString *rmqId in rmqIds) { + int64_t rmqIdValue = [rmqId longLongValue]; + if (rmqIdValue > maxRmqId) { + maxRmqId = rmqIdValue; + } + } + maxRmqId++; + if (maxRmqId >= self.rmqId) { + [self saveLastOutgoingRmqId:maxRmqId]; + } + return [self.rmq2Store deleteMessagesFromTable:kTableOutgoingRmqMessages withRmqIds:rmqIds]; +} + +- (void)removeS2dIds:(NSArray *)s2dIds { + [self.rmq2Store deleteMessagesFromTable:kTableS2DRmqIds withRmqIds:s2dIds]; +} + +#pragma mark - Sync Messages + +// TODO: RMQManager should also have a cache for all the sync messages +// so we don't hit the DB each time. +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID { + return [self.rmq2Store querySyncMessageWithRmqID:rmqID]; +} + +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID { + return [self.rmq2Store deleteSyncMessageWithRmqID:rmqID]; +} + +- (int)deleteExpiredOrFinishedSyncMessages:(NSError **)error { + return [self.rmq2Store deleteExpiredOrFinishedSyncMessages:error]; +} + +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError *__autoreleasing *)error { + return [self.rmq2Store saveSyncMessageWithRmqID:rmqID + expirationTime:expirationTime + apnsReceived:apnsReceived + mcsReceived:mcsReceived + error:error]; +} + +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID error:(NSError **)error { + return [self.rmq2Store updateSyncMessageViaAPNSWithRmqID:rmqID error:error]; +} + +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID error:(NSError **)error { + return [self.rmq2Store updateSyncMessageViaMCSWithRmqID:rmqID error:error]; +} + +#pragma mark - Testing + ++ (void)removeDatabaseWithName:(NSString *)dbName { + [FIRMessagingRmq2PersistentStore removeDatabase:dbName]; +} + +#pragma mark - Private + +- (int64_t)nextRmqId { + return ++self.rmqId; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.h new file mode 100644 index 0000000..169f60e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSUInteger, FIRMessagingSecureSocketState){ + kFIRMessagingSecureSocketNotOpen = 0, + kFIRMessagingSecureSocketOpening, + kFIRMessagingSecureSocketOpen, + kFIRMessagingSecureSocketClosing, + kFIRMessagingSecureSocketClosed, + kFIRMessagingSecureSocketError +}; + +@class FIRMessagingSecureSocket; + +@protocol FIRMessagingSecureSocketDelegate + +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didReceiveData:(NSData *)data + withTag:(int8_t)tag; +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didSendProtoWithTag:(int8_t)tag + rmqId:(NSString *)rmqId; +- (void)secureSocketDidConnect:(FIRMessagingSecureSocket *)socket; +- (void)didDisconnectWithSecureSocket:(FIRMessagingSecureSocket *)socket; + +@end + +/** + * This manages the input/output streams connected to the MCS server. Used to receive data from + * the server and send to it over the wire. + */ +@interface FIRMessagingSecureSocket : NSObject + +@property(nonatomic, readwrite, weak) id delegate; +@property(nonatomic, readonly, assign) FIRMessagingSecureSocketState state; + +- (void)connectToHost:(NSString *)host port:(NSUInteger)port onRunLoop:(NSRunLoop *)runLoop; +- (void)disconnect; +- (void)sendData:(NSData *)data withTag:(int8_t)tag rmqId:(NSString *)rmqId; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.m new file mode 100644 index 0000000..dd78a76 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.m @@ -0,0 +1,444 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingSecureSocket.h" + +#import +#import +#import + +#import "FIRMessagingCodedInputStream.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPacketQueue.h" + +static const NSUInteger kMaxBufferLength = 1024 * 1024; // 1M +static const NSUInteger kBufferLengthIncrement = 16 * 1024; // 16k +static const uint8_t kVersion = 40; +static const uint8_t kInvalidTag = -1; + +typedef NS_ENUM(NSUInteger, FIRMessagingSecureSocketReadResult) { + kFIRMessagingSecureSocketReadResultNone, + kFIRMessagingSecureSocketReadResultIncomplete, + kFIRMessagingSecureSocketReadResultCorrupt, + kFIRMessagingSecureSocketReadResultSuccess +}; + +static int32_t LogicalRightShift32(int32_t value, int32_t spaces) { + return (int32_t)((uint32_t)(value) >> spaces); +} + +static NSUInteger SerializedSize(int32_t value) { + NSUInteger bytes = 0; + while (YES) { + if ((value & ~0x7F) == 0) { + bytes += sizeof(uint8_t); + return bytes; + } else { + bytes += sizeof(uint8_t); + value = LogicalRightShift32(value, 7); + } + } +} + +@interface FIRMessagingSecureSocket() + +@property(nonatomic, readwrite, assign) FIRMessagingSecureSocketState state; +@property(nonatomic, readwrite, strong) NSInputStream *inStream; +@property(nonatomic, readwrite, strong) NSOutputStream *outStream; + +@property(nonatomic, readwrite, strong) NSMutableData *inputBuffer; +@property(nonatomic, readwrite, assign) NSUInteger inputBufferLength; +@property(nonatomic, readwrite, strong) NSMutableData *outputBuffer; +@property(nonatomic, readwrite, assign) NSUInteger outputBufferLength; + +@property(nonatomic, readwrite, strong) FIRMessagingPacketQueue *packetQueue; +@property(nonatomic, readwrite, assign) BOOL isVersionSent; +@property(nonatomic, readwrite, assign) BOOL isVersionReceived; +@property(nonatomic, readwrite, assign) BOOL isInStreamOpen; +@property(nonatomic, readwrite, assign) BOOL isOutStreamOpen; + +@property(nonatomic, readwrite, strong) NSRunLoop *runLoop; +@property(nonatomic, readwrite, strong) NSString *currentRmqIdBeingSent; +@property(nonatomic, readwrite, assign) int8_t currentProtoTypeBeingSent; + +@end + +@implementation FIRMessagingSecureSocket + +- (instancetype)init { + self = [super init]; + if (self) { + _state = kFIRMessagingSecureSocketNotOpen; + _inputBuffer = [NSMutableData dataWithLength:kBufferLengthIncrement]; + _packetQueue = [[FIRMessagingPacketQueue alloc] init]; + _currentProtoTypeBeingSent = kInvalidTag; + } + return self; +} + +- (void)dealloc { + [self disconnect]; +} + +- (void)connectToHost:(NSString *)host + port:(NSUInteger)port + onRunLoop:(NSRunLoop *)runLoop { + _FIRMessagingDevAssert(host != nil, @"Invalid host"); + _FIRMessagingDevAssert(runLoop != nil, @"Invalid runloop"); + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketNotOpen, @"Socket is already connected"); + + if (!host || self.state != kFIRMessagingSecureSocketNotOpen) { + return; + } + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket000, + @"Opening secure socket to FIRMessaging service"); + self.state = kFIRMessagingSecureSocketOpening; + self.runLoop = runLoop; + CFReadStreamRef inputStreamRef; + CFWriteStreamRef outputStreamRef; + CFStreamCreatePairWithSocketToHost(NULL, + (__bridge CFStringRef)host, + (int)port, + &inputStreamRef, + &outputStreamRef); + self.inStream = CFBridgingRelease(inputStreamRef); + self.outStream = CFBridgingRelease(outputStreamRef); + if (!self.inStream || !self.outStream) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket001, + @"Failed to initialize socket."); + return; + } + + self.isInStreamOpen = NO; + self.isOutStreamOpen = NO; + + BOOL isVOIPSocket = NO; + + [self openStream:self.outStream isVOIPStream:isVOIPSocket]; + [self openStream:self.inStream isVOIPStream:isVOIPSocket]; +} + +- (void)disconnect { + if (self.state == kFIRMessagingSecureSocketClosing) { + return; + } + if (!self.inStream && !self.outStream) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket002, + @"The socket is not open or already closed."); + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketClosed || self.state == kFIRMessagingSecureSocketNotOpen, + @"Socket is already disconnected."); + return; + } + + self.state = kFIRMessagingSecureSocketClosing; + if (self.inStream) { + [self closeStream:self.inStream]; + self.inStream = nil; + } + if (self.outStream) { + [self closeStream:self.outStream]; + self.outStream = nil; + } + self.state = kFIRMessagingSecureSocketClosed; + [self.delegate didDisconnectWithSecureSocket:self]; +} + +- (void)sendData:(NSData *)data withTag:(int8_t)tag rmqId:(NSString *)rmqId { + [self.packetQueue push:[FIRMessagingPacket packetWithTag:tag rmqId:rmqId data:data]]; + if ([self.outStream hasSpaceAvailable]) { + [self performWrite]; + } +} + +#pragma mark - NSStreamDelegate + +- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { + switch (eventCode) { + case NSStreamEventHasBytesAvailable: + if (self.state != kFIRMessagingSecureSocketOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket003, + @"Try to read from socket that is not opened"); + return; + } + _FIRMessagingDevAssert(stream == self.inStream, @"Incorrect stream"); + if (![self performRead]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket004, + @"Error occurred when reading incoming stream"); + [self disconnect]; + } + break; + case NSStreamEventEndEncountered: + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeSecureSocket005, @"%@ end encountered", + stream == self.inStream + ? @"Input stream" + : (stream == self.outStream ? @"Output stream" : @"Unknown stream")); + [self disconnect]; + break; + case NSStreamEventOpenCompleted: + if (stream == self.inStream) { + self.isInStreamOpen = YES; + } else if (stream == self.outStream) { + self.isOutStreamOpen = YES; + } + if (self.isInStreamOpen && self.isOutStreamOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket006, + @"Secure socket to FIRMessaging service opened"); + self.state = kFIRMessagingSecureSocketOpen; + [self.delegate secureSocketDidConnect:self]; + } + break; + case NSStreamEventErrorOccurred: { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeSecureSocket007, @"%@ error occurred", + stream == self.inStream + ? @"Input stream" + : (stream == self.outStream ? @"Output stream" : @"Unknown stream")); + [self disconnect]; + break; + } + case NSStreamEventHasSpaceAvailable: + if (self.state != kFIRMessagingSecureSocketOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket008, + @"Try to write to socket that is not opened"); + return; + } + _FIRMessagingDevAssert(stream == self.outStream, @"Incorrect stream"); + [self performWrite]; + break; + default: + break; + } +} + +#pragma mark - Private + +- (void)openStream:(NSStream *)stream isVOIPStream:(BOOL)isVOIPStream { + _FIRMessagingDevAssert(stream != nil, @"Invalid stream"); + _FIRMessagingDevAssert(self.runLoop != nil, @"Invalid runloop"); + + if (stream) { + _FIRMessagingDevAssert([stream streamStatus] == NSStreamStatusNotOpen, @"Stream already open"); + if ([stream streamStatus] != NSStreamStatusNotOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket009, + @"stream should not be open."); + return; + } + [stream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL + forKey:NSStreamSocketSecurityLevelKey]; + if (isVOIPStream) { + [stream setProperty:NSStreamNetworkServiceTypeVoIP + forKey:NSStreamNetworkServiceType]; + } + stream.delegate = self; + [stream scheduleInRunLoop:self.runLoop forMode:NSDefaultRunLoopMode]; + [stream open]; + } +} + +- (void)closeStream:(NSStream *)stream { + _FIRMessagingDevAssert(stream != nil, @"Invalid stream"); + _FIRMessagingDevAssert(self.runLoop != nil, @"Invalid runloop"); + + if (stream) { + [stream close]; + [stream removeFromRunLoop:self.runLoop forMode:NSDefaultRunLoopMode]; + stream.delegate = nil; + } +} + +- (BOOL)performRead { + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketOpen, @"Socket should be open"); + + if (!self.isVersionReceived) { + self.isVersionReceived = YES; + uint8_t versionByte = 0; + NSInteger bytesRead = [self.inStream read:&versionByte maxLength:sizeof(uint8_t)]; + if (bytesRead != sizeof(uint8_t) || kVersion != versionByte) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket010, + @"Version do not match. Received %d, Expecting %d", versionByte, + kVersion); + return NO; + } + } + + while (YES) { + BOOL isInputBufferValid = [self.inputBuffer length] > 0; + _FIRMessagingDevAssert(isInputBufferValid, + @"Invalid input buffer size %lu. Used bytes length %lu, buffer content: %@", + _FIRMessaging_UL([self.inputBuffer length]), + _FIRMessaging_UL(self.inputBufferLength), + self.inputBuffer); + if (!isInputBufferValid) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket011, + @"Input buffer is not valid."); + return NO; + } + + if (![self.inStream hasBytesAvailable]) { + break; + } + + // try to read more data + uint8_t *unusedBufferPtr = (uint8_t *)self.inputBuffer.mutableBytes + self.inputBufferLength; + NSUInteger unusedBufferLength = [self.inputBuffer length] - self.inputBufferLength; + NSInteger bytesRead = [self.inStream read:unusedBufferPtr maxLength:unusedBufferLength]; + if (bytesRead <= 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket012, + @"Failed to read input stream. Bytes read %ld, Used buffer size %lu, " + @"Unused buffer size %lu", + _FIRMessaging_UL(bytesRead), _FIRMessaging_UL(self.inputBufferLength), + _FIRMessaging_UL(unusedBufferLength)); + break; + } + // did successfully read some more data + self.inputBufferLength += (NSUInteger)bytesRead; + + if ([self.inputBuffer length] <= self.inputBufferLength) { + // shouldn't be reading more than 1MB of data in one go + if ([self.inputBuffer length] + kBufferLengthIncrement > kMaxBufferLength) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket013, + @"Input buffer exceed 1M, disconnect socket"); + return NO; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket014, + @"Input buffer limit exceeded. Used input buffer size %lu, " + @"Total input buffer size %lu. No unused buffer left. " + @"Increase buffer size.", + _FIRMessaging_UL(self.inputBufferLength), + _FIRMessaging_UL([self.inputBuffer length])); + [self.inputBuffer increaseLengthBy:kBufferLengthIncrement]; + _FIRMessagingDevAssert([self.inputBuffer length] > self.inputBufferLength, @"Invalid buffer size"); + } + + while (self.inputBufferLength > 0 && [self.inputBuffer length] > 0) { + _FIRMessagingDevAssert([self.inputBuffer length] >= self.inputBufferLength, + @"Buffer longer than length"); + NSRange inputRange = NSMakeRange(0, self.inputBufferLength); + size_t protoBytes = 0; + // read the actual proto data coming in + FIRMessagingSecureSocketReadResult readResult = + [self processCurrentInputBuffer:[self.inputBuffer subdataWithRange:inputRange] + outOffset:&protoBytes]; + // Corrupt data encountered, stop processing. + if (readResult == kFIRMessagingSecureSocketReadResultCorrupt) { + return NO; + // Incomplete data, keep trying to read by loading more from the stream. + } else if (readResult == kFIRMessagingSecureSocketReadResultIncomplete) { + break; + } + _FIRMessagingDevAssert(self.inputBufferLength >= protoBytes, @"More bytes than buffer can handle"); + // we have read (0, protoBytes) of data in the inputBuffer + if (protoBytes == self.inputBufferLength) { + // did completely read the buffer data can be reset for further processing + self.inputBufferLength = 0; + } else { + // delete processed bytes while maintaining the buffer size. + NSUInteger prevLength __unused = [self.inputBuffer length]; + // delete the processed bytes + [self.inputBuffer replaceBytesInRange:NSMakeRange(0, protoBytes) withBytes:NULL length:0]; + // reallocate more data + [self.inputBuffer increaseLengthBy:protoBytes]; + _FIRMessagingDevAssert([self.inputBuffer length] == prevLength, + @"Invalid input buffer size %lu. Used bytes length %lu, " + @"buffer content: %@", + _FIRMessaging_UL([self.inputBuffer length]), + _FIRMessaging_UL(self.inputBufferLength), + self.inputBuffer); + self.inputBufferLength -= protoBytes; + } + } + } + return YES; +} + +- (FIRMessagingSecureSocketReadResult)processCurrentInputBuffer:(NSData *)readData + outOffset:(size_t *)outOffset { + *outOffset = 0; + + FIRMessagingCodedInputStream *input = [[FIRMessagingCodedInputStream alloc] initWithData:readData]; + int8_t rawTag; + if (![input readTag:&rawTag]) { + return kFIRMessagingSecureSocketReadResultIncomplete; + } + int32_t length; + if (![input readLength:&length]) { + return kFIRMessagingSecureSocketReadResultIncomplete; + } + // NOTE tag can be zero for |HeartbeatPing|, and length can be zero for |Close| proto + _FIRMessagingDevAssert(rawTag >= 0 && length >= 0, @"Invalid tag or length"); + if (rawTag < 0 || length < 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket015, @"Buffer data corrupted."); + return kFIRMessagingSecureSocketReadResultCorrupt; + } + NSData *data = [input readDataWithLength:(uint32_t)length]; + if (data == nil) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket016, + @"Incomplete data, buffered data length %ld, expected length %d", + _FIRMessaging_UL(self.inputBufferLength), length); + return kFIRMessagingSecureSocketReadResultIncomplete; + } + [self.delegate secureSocket:self didReceiveData:data withTag:rawTag]; + *outOffset = input.offset; + return kFIRMessagingSecureSocketReadResultSuccess; +} + +- (void)performWrite { + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketOpen, @"Invalid socket state"); + + if (!self.isVersionSent) { + self.isVersionSent = YES; + uint8_t versionByte = kVersion; + [self.outStream write:&versionByte maxLength:sizeof(uint8_t)]; + } + + while (!self.packetQueue.isEmpty && self.outStream.hasSpaceAvailable) { + if (self.outputBuffer.length == 0) { + // serialize new packets only when the output buffer is flushed. + FIRMessagingPacket *packet = [self.packetQueue pop]; + self.currentRmqIdBeingSent = packet.rmqId; + self.currentProtoTypeBeingSent = packet.tag; + NSUInteger length = SerializedSize(packet.tag) + + SerializedSize((int)packet.data.length) + packet.data.length; + self.outputBuffer = [NSMutableData dataWithLength:length]; + GPBCodedOutputStream *output = [GPBCodedOutputStream streamWithData:self.outputBuffer]; + [output writeRawVarint32:packet.tag]; + [output writeBytesNoTag:packet.data]; + self.outputBufferLength = 0; + } + + // flush the output buffer. + NSInteger written = [self.outStream write:self.outputBuffer.bytes + self.outputBufferLength + maxLength:self.outputBuffer.length - self.outputBufferLength]; + if (written <= 0) { + continue; + } + self.outputBufferLength += (NSUInteger)written; + if (self.outputBufferLength >= self.outputBuffer.length) { + self.outputBufferLength = 0; + self.outputBuffer = nil; + [self.delegate secureSocket:self + didSendProtoWithTag:self.currentProtoTypeBeingSent + rmqId:self.currentRmqIdBeingSent]; + self.currentRmqIdBeingSent = nil; + self.currentProtoTypeBeingSent = kInvalidTag; + } + } +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.h new file mode 100644 index 0000000..3d30bdb --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRMessagingRmqManager; + +/** + * Handle sync messages being received both via MCS and APNS. + */ +@interface FIRMessagingSyncMessageManager : NSObject + +/** + * Initialize sync message manager. + * + * @param rmqManager The RMQ manager on the client. + * + * @return Sync message manager. + */ +- (instancetype)initWithRmqManager:(FIRMessagingRmqManager *)rmqManager; + +/** + * Remove expired sync message from persistent store. Also removes messages that have + * been received both via APNS and MCS. + */ +- (void)removeExpiredSyncMessages; + +/** + * App did recive a sync message via APNS. + * + * @param message The sync message received. + * + * @return YES if the message is a duplicate of an already received sync message else NO. + */ +- (BOOL)didReceiveAPNSSyncMessage:(NSDictionary *)message; + +/** + * App did receive a sync message via MCS. + * + * @param message The sync message received. + * + * @return YES if the message is a duplicate of an already received sync message else NO. + */ +- (BOOL)didReceiveMCSSyncMessage:(NSDictionary *)message; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.m new file mode 100644 index 0000000..1257b02 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.m @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingSyncMessageManager.h" + +#import "FIRMessagingConstants.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPersistentSyncMessage.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingUtilities.h" + +static const int64_t kDefaultSyncMessageTTL = 4 * 7 * 24 * 60 * 60; // 4 weeks +// 4 MB of free space is required to persist Sync messages +static const uint64_t kMinFreeDiskSpaceInMB = 1; + +@interface FIRMessagingSyncMessageManager() + +@property(nonatomic, readwrite, strong) FIRMessagingRmqManager *rmqManager; + +@end + +@implementation FIRMessagingSyncMessageManager + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithRmqManager:(FIRMessagingRmqManager *)rmqManager { + _FIRMessagingDevAssert(rmqManager, @"Invalid nil rmq manager while initalizing sync message manager"); + self = [super init]; + if (self) { + _rmqManager = rmqManager; + } + return self; +} + +- (void)removeExpiredSyncMessages { + NSError *error; + int deleteCount = [self.rmqManager deleteExpiredOrFinishedSyncMessages:&error]; + if (error) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager000, + @"Error while deleting expired sync messages %@", error); + } else if (deleteCount > 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSyncMessageManager001, + @"Successfully deleted %d sync messages from store", deleteCount); + } +} + +- (BOOL)didReceiveAPNSSyncMessage:(NSDictionary *)message { + return [self didReceiveSyncMessage:message viaAPNS:YES viaMCS:NO]; +} + +- (BOOL)didReceiveMCSSyncMessage:(NSDictionary *)message { + return [self didReceiveSyncMessage:message viaAPNS:NO viaMCS:YES]; +} + +- (BOOL)didReceiveSyncMessage:(NSDictionary *)message + viaAPNS:(BOOL)viaAPNS + viaMCS:(BOOL)viaMCS { + NSString *rmqID = message[kFIRMessagingMessageIDKey]; + _FIRMessagingDevAssert([rmqID length], @"Invalid nil rmqID for message"); + if (![rmqID length]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager002, + @"Invalid nil rmqID for sync message."); + return NO; + } + + FIRMessagingPersistentSyncMessage *persistentMessage = + [self.rmqManager querySyncMessageWithRmqID:rmqID]; + + NSError *error; + if (!persistentMessage) { + + // Do not persist the new message if we don't have enough disk space + uint64_t freeDiskSpace = FIRMessagingGetFreeDiskSpaceInMB(); + if (freeDiskSpace < kMinFreeDiskSpaceInMB) { + return NO; + } + + int64_t expirationTime = [[self class] expirationTimeForSyncMessage:message]; + if (![self.rmqManager saveSyncMessageWithRmqID:rmqID + expirationTime:expirationTime + apnsReceived:viaAPNS + mcsReceived:viaMCS + error:&error]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager003, + @"Failed to save sync message with rmqID %@", rmqID); + } else { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeSyncMessageManager004, + @"Added sync message to cache: %@", rmqID); + } + return NO; + } + + if (viaAPNS && !persistentMessage.apnsReceived) { + persistentMessage.apnsReceived = YES; + if (![self.rmqManager updateSyncMessageViaAPNSWithRmqID:rmqID error:&error]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager005, + @"Failed to update APNS state for sync message %@", rmqID); + } + } else if (viaMCS && !persistentMessage.mcsReceived) { + persistentMessage.mcsReceived = YES; + if (![self.rmqManager updateSyncMessageViaMCSWithRmqID:rmqID error:&error]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager006, + @"Failed to update MCS state for sync message %@", rmqID); + } + } + + // Received message via both ways we can safely delete it. + if (persistentMessage.apnsReceived && persistentMessage.mcsReceived) { + if (![self.rmqManager deleteSyncMessageWithRmqID:rmqID]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager007, + @"Failed to delete sync message %@", rmqID); + } else { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeSyncMessageManager008, + @"Successfully deleted sync message from cache %@", rmqID); + } + } + + // Already received this message either via MCS or APNS. + return YES; +} + ++ (int64_t)expirationTimeForSyncMessage:(NSDictionary *)message { + int64_t ttl = kDefaultSyncMessageTTL; + if (message[kFIRMessagingMessageSyncMessageTTLKey]) { + ttl = [message[kFIRMessagingMessageSyncMessageTTLKey] longLongValue]; + } + int64_t currentTime = FIRMessagingCurrentTimestampInSeconds(); + return currentTime + ttl; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.h new file mode 100644 index 0000000..ea98e6d --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingCheckinService.h" +#import "FIRMessagingTopicsCommon.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * An asynchronous NSOperation subclass which performs a single network request for a topic + * subscription operation. Once completed, it calls its provided completion handler. + */ +@interface FIRMessagingTopicOperation : NSOperation + +@property(nonatomic, readonly, copy) NSString *topic; +@property(nonatomic, readonly, assign) FIRMessagingTopicAction action; +@property(nonatomic, readonly, copy) NSString *token; +@property(nonatomic, readonly, copy, nullable) NSDictionary *options; +@property(nonatomic, readonly, strong) FIRMessagingCheckinService *checkinService; + +- (instancetype)initWithTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + token:(NSString *)token + options:(nullable NSDictionary *)options + checkinService:(FIRMessagingCheckinService *)checkinService + completion:(FIRMessagingTopicOperationCompletion)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.m new file mode 100644 index 0000000..6703178 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.m @@ -0,0 +1,263 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingTopicOperation.h" + +#import "FIRMessagingCheckinService.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +#define DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS 0 + +static NSString *const kFIRMessagingSubscribeServerHost = + @"https://iid.googleapis.com/iid/register"; + +NSString *FIRMessagingSubscriptionsServer() { + static NSString *serverHost = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *environment = [[NSProcessInfo processInfo] environment]; + NSString *customServerHost = environment[@"FCM_SERVER_ENDPOINT"]; + if (customServerHost.length) { + serverHost = customServerHost; + } else { + serverHost = kFIRMessagingSubscribeServerHost; + } + }); + return serverHost; +} + +@interface FIRMessagingTopicOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, copy) NSString *topic; +@property(nonatomic, readwrite, assign) FIRMessagingTopicAction action; +@property(nonatomic, readwrite, copy) NSString *token; +@property(nonatomic, readwrite, copy) NSDictionary *options; +@property(nonatomic, readwrite, strong) FIRMessagingCheckinService *checkinService; +@property(nonatomic, readwrite, copy) FIRMessagingTopicOperationCompletion completion; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; + +@end + +@implementation FIRMessagingTopicOperation + ++ (NSURLSession *)sharedSession { + static NSURLSession *subscriptionOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + subscriptionOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + subscriptionOperationSharedSession.sessionDescription = @"com.google.fcm.topics.session"; + }); + return subscriptionOperationSharedSession; +} + +- (instancetype)initWithTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + token:(NSString *)token + options:(NSDictionary *)options + checkinService:(FIRMessagingCheckinService *)checkinService + completion:(FIRMessagingTopicOperationCompletion)completion { + if (self = [super init]) { + _topic = topic; + _action = action; + _token = token; + _options = options; + _checkinService = checkinService; + _completion = completion; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _topic = nil; + _token = nil; + _checkinService = nil; + _completion = nil; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + NSError *error = + [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubOperationIsCancelled]; + [self finishWithError:error]; + return; + } + + [self setExecuting:YES]; + + [self performSubscriptionChange]; +} + +- (void)finishWithError:(NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + if (self.completion) { + self.completion(error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + NSError *error = [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubOperationIsCancelled]; + [self finishWithError:error]; +} + +- (void)performSubscriptionChange { + + NSURL *url = [NSURL URLWithString:FIRMessagingSubscriptionsServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + NSString *appIdentifier = FIRMessagingAppIdentifier(); + NSString *deviceAuthID = self.checkinService.deviceAuthID; + NSString *secretToken = self.checkinService.secretToken; + NSString *authString = [NSString stringWithFormat:@"AidLogin %@:%@", deviceAuthID, secretToken]; + [request setValue:authString forHTTPHeaderField:@"Authorization"]; + [request setValue:appIdentifier forHTTPHeaderField:@"app"]; + [request setValue:self.checkinService.versionInfo forHTTPHeaderField:@"info"]; + + // Topic can contain special characters (like `%`) so encode the value. + NSCharacterSet *characterSet = [NSCharacterSet URLQueryAllowedCharacterSet]; + NSString *encodedTopic = + [self.topic stringByAddingPercentEncodingWithAllowedCharacters:characterSet]; + if (encodedTopic == nil) { + // The transformation was somehow not possible, so use the original topic. + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTopicOptionTopicEncodingFailed, + @"Unable to encode the topic '%@' during topic subscription change. " + @"Please ensure that the topic name contains only valid characters.", + self.topic); + encodedTopic = self.topic; + } + + NSMutableString *content = [NSMutableString stringWithFormat: + @"sender=%@&app=%@&device=%@&" + @"app_ver=%@&X-gcm.topic=%@&X-scope=%@", + self.token, + appIdentifier, + deviceAuthID, + FIRMessagingCurrentAppVersion(), + encodedTopic, + encodedTopic]; + + if (self.action == FIRMessagingTopicActionUnsubscribe) { + [content appendString:@"&delete=true"]; + } + + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeTopicOption000, @"Topic subscription request: %@", + content); + + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + [request setHTTPMethod:@"POST"]; + +#if DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS + NSDate *start = [NSDate date]; +#endif + + FIRMessaging_WEAKIFY(self) + void(^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *URLResponse, NSError *error) { + FIRMessaging_STRONGIFY(self) + if (error) { + // Our operation could have been cancelled, which would result in our data task's error being + // NSURLErrorCancelled + if (error.code == NSURLErrorCancelled) { + // We would only have been cancelled in the -cancel method, which will call finish for us + // so just return and do nothing. + return; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOption001, + @"Device registration HTTP fetch error. Error Code: %ld", + _FIRMessaging_L(error.code)); + [self finishWithError:error]; + return; + } + NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (response.length == 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOperationEmptyResponse, + @"Invalid registration response - zero length."); + [self finishWithError:[NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeUnknown]]; + return; + } + NSArray *parts = [response componentsSeparatedByString:@"="]; + _FIRMessagingDevAssert(parts.count, @"Invalid registration response"); + if (![parts[0] isEqualToString:@"token"] || parts.count <= 1) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOption002, + @"Invalid registration response %@", response); + [self finishWithError:[NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeUnknown]]; + return; + } +#if DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS + NSTimeInterval duration = -[start timeIntervalSinceNow]; + FIRMessagingLoggerDebug(@"%@ change took %.2fs", self.topic, duration); +#endif + [self finishWithError:nil]; + + }; + + NSURLSession *urlSession = [FIRMessagingTopicOperation sharedSession]; + + self.dataTask = [urlSession dataTaskWithRequest:request completionHandler:requestHandler]; + NSString *description; + if (_action == FIRMessagingTopicActionSubscribe) { + description = [NSString stringWithFormat:@"com.google.fcm.topics.subscribe: %@", _topic]; + } else { + description = [NSString stringWithFormat:@"com.google.fcm.topics.unsubscribe: %@", _topic]; + } + self.dataTask.taskDescription = description; + [self.dataTask resume]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicsCommon.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicsCommon.h new file mode 100644 index 0000000..030b3ff --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicsCommon.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on a subscription topic. + */ +typedef NS_ENUM(NSInteger, FIRMessagingTopicAction) { + FIRMessagingTopicActionSubscribe, + FIRMessagingTopicActionUnsubscribe +}; + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.h new file mode 100644 index 0000000..58475bf --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(int8_t, FIRMessagingProtoTag) { + kFIRMessagingProtoTagInvalid = -1, + kFIRMessagingProtoTagHeartbeatPing = 0, + kFIRMessagingProtoTagHeartbeatAck = 1, + kFIRMessagingProtoTagLoginRequest = 2, + kFIRMessagingProtoTagLoginResponse = 3, + kFIRMessagingProtoTagClose = 4, + kFIRMessagingProtoTagIqStanza = 7, + kFIRMessagingProtoTagDataMessageStanza = 8, +}; + +@class GPBMessage; + +#pragma mark - Protocol Buffers + +FOUNDATION_EXPORT FIRMessagingProtoTag FIRMessagingGetTagForProto(GPBMessage *protoClass); +FOUNDATION_EXPORT Class FIRMessagingGetClassForTag(FIRMessagingProtoTag tag); + +#pragma mark - MCS + +FOUNDATION_EXPORT NSString *FIRMessagingGetRmq2Id(GPBMessage *proto); +FOUNDATION_EXPORT void FIRMessagingSetRmq2Id(GPBMessage *proto, NSString *pID); +FOUNDATION_EXPORT int FIRMessagingGetLastStreamId(GPBMessage *proto); +FOUNDATION_EXPORT void FIRMessagingSetLastStreamId(GPBMessage *proto, int sid); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRMessagingCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRMessagingCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRMessagingCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRMessagingAppIdentifier(void); + +#pragma mark - Others + +FOUNDATION_EXPORT uint64_t FIRMessagingGetFreeDiskSpaceInMB(void); +FOUNDATION_EXPORT UIApplication *FIRMessagingUIApplication(void); +FOUNDATION_EXPORT NSSearchPathDirectory FIRMessagingSupportedDirectory(void); + + diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.m new file mode 100644 index 0000000..743caed --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.m @@ -0,0 +1,196 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingUtilities.h" + +#import "Protos/GtalkCore.pbobjc.h" + +#import "FIRMessagingLogger.h" + +#import + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static const uint64_t kBytesToMegabytesDivisor = 1024 * 1024LL; + +#pragma mark - Protocol Buffers + +FIRMessagingProtoTag FIRMessagingGetTagForProto(GPBMessage *proto) { + if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) { + return kFIRMessagingProtoTagHeartbeatPing; + } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) { + return kFIRMessagingProtoTagHeartbeatAck; + } else if ([proto isKindOfClass:[GtalkLoginRequest class]]) { + return kFIRMessagingProtoTagLoginRequest; + } else if ([proto isKindOfClass:[GtalkLoginResponse class]]) { + return kFIRMessagingProtoTagLoginResponse; + } else if ([proto isKindOfClass:[GtalkClose class]]) { + return kFIRMessagingProtoTagClose; + } else if ([proto isKindOfClass:[GtalkIqStanza class]]) { + return kFIRMessagingProtoTagIqStanza; + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + return kFIRMessagingProtoTagDataMessageStanza; + } + return kFIRMessagingProtoTagInvalid; +} + +Class FIRMessagingGetClassForTag(FIRMessagingProtoTag tag) { + switch (tag) { + case kFIRMessagingProtoTagHeartbeatPing: + return GtalkHeartbeatPing.class; + case kFIRMessagingProtoTagHeartbeatAck: + return GtalkHeartbeatAck.class; + case kFIRMessagingProtoTagLoginRequest: + return GtalkLoginRequest.class; + case kFIRMessagingProtoTagLoginResponse: + return GtalkLoginResponse.class; + case kFIRMessagingProtoTagClose: + return GtalkClose.class; + case kFIRMessagingProtoTagIqStanza: + return GtalkIqStanza.class; + case kFIRMessagingProtoTagDataMessageStanza: + return GtalkDataMessageStanza.class; + case kFIRMessagingProtoTagInvalid: + return NSNull.class; + } + return NSNull.class; +} + +#pragma mark - MCS + +NSString *FIRMessagingGetRmq2Id(GPBMessage *proto) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + if (((GtalkIqStanza *)proto).hasPersistentId) { + return ((GtalkIqStanza *)proto).persistentId; + } + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + if (((GtalkDataMessageStanza *)proto).hasPersistentId) { + return ((GtalkDataMessageStanza *)proto).persistentId; + } + } + return nil; +} + +void FIRMessagingSetRmq2Id(GPBMessage *proto, NSString *pID) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + ((GtalkIqStanza *)proto).persistentId = pID; + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + ((GtalkDataMessageStanza *)proto).persistentId = pID; + } +} + +int FIRMessagingGetLastStreamId(GPBMessage *proto) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + if (((GtalkIqStanza *)proto).hasLastStreamIdReceived) { + return ((GtalkIqStanza *)proto).lastStreamIdReceived; + } + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + if (((GtalkDataMessageStanza *)proto).hasLastStreamIdReceived) { + return ((GtalkDataMessageStanza *)proto).lastStreamIdReceived; + } + } else if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) { + if (((GtalkHeartbeatPing *)proto).hasLastStreamIdReceived) { + return ((GtalkHeartbeatPing *)proto).lastStreamIdReceived; + } + } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) { + if (((GtalkHeartbeatAck *)proto).hasLastStreamIdReceived) { + return ((GtalkHeartbeatAck *)proto).lastStreamIdReceived; + } + } + return -1; +} + +void FIRMessagingSetLastStreamId(GPBMessage *proto, int sid) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + ((GtalkIqStanza *)proto).lastStreamIdReceived = sid; + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + ((GtalkDataMessageStanza *)proto).lastStreamIdReceived = sid; + } else if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) { + ((GtalkHeartbeatPing *)proto).lastStreamIdReceived = sid; + } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) { + ((GtalkHeartbeatAck *)proto).lastStreamIdReceived = sid; + } +} + +#pragma mark - Time + +int64_t FIRMessagingCurrentTimestampInSeconds(void) { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRMessagingCurrentTimestampInMilliseconds(void) { + return (int64_t)(FIRMessagingCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRMessagingCurrentAppVersion(void) { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities000, + @"Could not find current app version"); + return @""; + } + return version; +} + +NSString *FIRMessagingAppIdentifier(void) { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +uint64_t FIRMessagingGetFreeDiskSpaceInMB(void) { + NSError *error; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + + NSDictionary *attributesMap = + [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] + error:&error]; + if (attributesMap) { + uint64_t totalSizeInBytes __unused = [attributesMap[NSFileSystemSize] longLongValue]; + uint64_t freeSizeInBytes = [attributesMap[NSFileSystemFreeSize] longLongValue]; + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeUtilities001, @"Device has capacity %llu MB with %llu MB free.", + totalSizeInBytes / kBytesToMegabytesDivisor, freeSizeInBytes / kBytesToMegabytesDivisor); + return ((double)freeSizeInBytes) / kBytesToMegabytesDivisor; + } else { + FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities002, + @"Error in retreiving device's free memory %@", error); + return 0; + } +} + +UIApplication *FIRMessagingUIApplication(void) { + static Class applicationClass = nil; + // iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication + // responds to it. + if (![GULAppEnvironmentUtil isAppExtension]) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + return [applicationClass sharedApplication]; +} + +NSSearchPathDirectory FIRMessagingSupportedDirectory(void) { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.h new file mode 100644 index 0000000..cd292af --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Parsing utility for FIRMessaging Library versions. FIRMessaging Library follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRMessagingCurrentLibraryVersion(void); +/// Returns the current Major version of FIRMessaging library. +FOUNDATION_EXPORT int FIRMessagingCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of FIRMessaging library. +FOUNDATION_EXPORT int FIRMessagingCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of FIRMessaging library. +FOUNDATION_EXPORT int FIRMessagingCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRMessagingCurrentLibraryVersionIsBeta(void); diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.m new file mode 100644 index 0000000..1a3333c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.m @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingVersionUtilities.h" + +#import "FIRMessagingDefines.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRMessagingParseCurrentLibraryVersion(void) { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = [NSMutableString stringWithUTF8String:STR(FIRMessaging_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + _FIRMessagingDevAssert(allVersions.count == 3, @"Invalid versioning of FIRMessaging library"); + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + _FIRMessagingDevAssert(patchAndBetaVersion.count <= 2, @"Invalid versioning of FIRMessaging library"); + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRMessagingCurrentLibraryVersion(void) { + FIRMessagingParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRMessagingCurrentLibraryVersionMajor(void) { + FIRMessagingParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRMessagingCurrentLibraryVersionMinor(void) { + FIRMessagingParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRMessagingCurrentLibraryVersionPatch(void) { + FIRMessagingParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRMessagingCurrentLibraryVersionIsBeta(void) { + FIRMessagingParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging_Private.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging_Private.h new file mode 100644 index 0000000..0a95a50 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging_Private.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" + +@class FIRMessagingClient; +@class FIRMessagingPubSub; + +typedef NS_ENUM(int8_t, FIRMessagingNetworkStatus) { + kFIRMessagingReachabilityNotReachable = 0, + kFIRMessagingReachabilityReachableViaWiFi, + kFIRMessagingReachabilityReachableViaWWAN, +}; + +FOUNDATION_EXPORT NSString *const kFIRMessagingPlistAutoInitEnabled; +FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled; +FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyUseMessagingDelegate; +FOUNDATION_EXPORT NSString *const kFIRMessagingPlistUseMessagingDelegate; + +@interface FIRMessagingRemoteMessage () + +@property(nonatomic, copy) NSString *messageID; +@property(nonatomic, strong) NSDictionary *appData; + +@end + +@interface FIRMessaging () + +#pragma mark - Private API + +- (NSString *)defaultFcmToken; +- (FIRMessagingClient *)client; +- (FIRMessagingPubSub *)pubsub; + +// Create a sample message to be sent over the wire using FIRMessaging. Look at +// FIRMessagingService.h to see what each param signifies. ++ (NSMutableDictionary *)createFIRMessagingMessageWithMessage:(NSDictionary *)message + to:(NSString *)to + withID:(NSString *)msgID + timeToLive:(int64_t)ttl + delay:(int)delay; + +- (BOOL)isNetworkAvailable; +- (FIRMessagingNetworkStatus)networkType; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FirebaseMessaging.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FirebaseMessaging.h new file mode 100644 index 0000000..ef081c9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/FirebaseMessaging.h @@ -0,0 +1,17 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h new file mode 100644 index 0000000..d6a1639 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// @file FIRMessagingInternalUtilities.h +/// +/// Internal Class Names and Methods that other libs can query at runtime. + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the +/// required method. +static NSString *const kFIRMessagingSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRMessagingSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRMessagingSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.h new file mode 100644 index 0000000..fe14451 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface NSDictionary (FIRMessaging) + +/** + * Returns a string representation for the given dictionary. Assumes that all + * keys and values are strings. + * + * @return A string representation of all keys and values in the dictionary. + * The returned string is not pretty-printed. + */ +- (NSString *)fcm_string; + +/** + * Check if the dictionary has any non-string keys or values. + * + * @return YES if the dictionary has any non-string keys or values else NO. + */ +- (BOOL)fcm_hasNonStringKeysOrValues; + +/** + * Trims all (key, value) pair in a dictionary that are not strings. + * + * @return A new copied dictionary with all the non-string keys or values + * removed from the original dictionary. + */ +- (NSDictionary *)fcm_trimNonStringValues; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.m new file mode 100644 index 0000000..8df22ab --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.m @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSDictionary+FIRMessaging.h" + +@implementation NSDictionary (FIRMessaging) + +- (NSString *)fcm_string { + NSMutableString *dictAsString = [NSMutableString string]; + NSString *separator = @"|"; + for (id key in self) { + id value = self[key]; + if ([key isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { + [dictAsString appendFormat:@"%@:%@%@", key, value, separator]; + } + } + // remove the last separator + if ([dictAsString length]) { + [dictAsString deleteCharactersInRange:NSMakeRange(dictAsString.length - 1, 1)]; + } + return [dictAsString copy]; +} + +- (BOOL)fcm_hasNonStringKeysOrValues { + for (id key in self) { + id value = self[key]; + if (![key isKindOfClass:[NSString class]] || ![value isKindOfClass:[NSString class]]) { + return YES; + } + } + return NO; +} + +- (NSDictionary *)fcm_trimNonStringValues { + NSMutableDictionary *trimDictionary = + [NSMutableDictionary dictionaryWithCapacity:self.count]; + for (id key in self) { + id value = self[key]; + if ([key isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { + trimDictionary[(NSString *)key] = value; + } + } + return trimDictionary; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.h new file mode 100644 index 0000000..ae25b5b --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRMessagingDomain; + +typedef NS_ENUM(NSUInteger, FIRMessagingInternalErrorCode) { + // Unknown error. + kFIRMessagingErrorCodeUnknown = 0, + + // HTTP related errors. + kFIRMessagingErrorCodeAuthentication = 1, + kFIRMessagingErrorCodeNoAccess = 2, + kFIRMessagingErrorCodeTimeout = 3, + kFIRMessagingErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRMessagingErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRMessagingErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRMessagingErrorCodeInvalidRequest = 7, + + // FIRMessaging generic errors + kFIRMessagingErrorCodeMissingDeviceID = 501, + + // upstream send errors + kFIRMessagingErrorServiceNotAvailable = 1001, + kFIRMessagingErrorInvalidParameters = 1002, + kFIRMessagingErrorMissingTo = 1003, + kFIRMessagingErrorSave = 1004, + kFIRMessagingErrorSizeExceeded = 1005, + // Future Send Errors + + // MCS errors + // Already connected with MCS + kFIRMessagingErrorCodeAlreadyConnected = 2001, + + // PubSub errors + kFIRMessagingErrorCodePubSubAlreadySubscribed = 3001, + kFIRMessagingErrorCodePubSubAlreadyUnsubscribed = 3002, + kFIRMessagingErrorCodePubSubInvalidTopic = 3003, + kFIRMessagingErrorCodePubSubFIRMessagingNotSetup = 3004, + kFIRMessagingErrorCodePubSubOperationIsCancelled = 3005, +}; + +@interface NSError (FIRMessaging) + +@property(nonatomic, readonly) FIRMessagingInternalErrorCode fcmErrorCode; + ++ (NSError *)errorWithFCMErrorCode:(FIRMessagingInternalErrorCode)fcmErrorCode; ++ (NSError *)fcm_errorWithCode:(NSInteger)code userInfo:(NSDictionary *)userInfo; + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.m new file mode 100644 index 0000000..e4b8736 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRMessaging.h" + +NSString *const kFIRMessagingDomain = @"com.google.fcm"; + +@implementation NSError (FIRMessaging) + +- (FIRMessagingInternalErrorCode)fcmErrorCode { + return (FIRMessagingInternalErrorCode)self.code; +} + ++ (NSError *)errorWithFCMErrorCode:(FIRMessagingInternalErrorCode)fcmErrorCode { + return [NSError errorWithDomain:kFIRMessagingDomain code:fcmErrorCode userInfo:nil]; +} + ++ (NSError *)fcm_errorWithCode:(NSInteger)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRMessagingDomain code:code userInfo:userInfo]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.h new file mode 100644 index 0000000..46d2d9c --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.h @@ -0,0 +1,1374 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_core.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GtalkAppData; +@class GtalkCellTower; +@class GtalkClientEvent; +@class GtalkErrorInfo; +@class GtalkExtension; +@class GtalkHeartbeatConfig; +@class GtalkHeartbeatStat; +@class GtalkPresenceStanza; +@class GtalkSetting; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GtalkLoginRequest_AuthService + +typedef GPB_ENUM(GtalkLoginRequest_AuthService) { + GtalkLoginRequest_AuthService_Mail = 0, + GtalkLoginRequest_AuthService_AndroidCloudToDeviceMessage = 1, + GtalkLoginRequest_AuthService_AndroidId = 2, +}; + +GPBEnumDescriptor *GtalkLoginRequest_AuthService_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkLoginRequest_AuthService_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkMessageStanza_MessageType + +typedef GPB_ENUM(GtalkMessageStanza_MessageType) { + GtalkMessageStanza_MessageType_Normal = 0, + GtalkMessageStanza_MessageType_Chat = 1, + GtalkMessageStanza_MessageType_Groupchat = 2, + GtalkMessageStanza_MessageType_Headline = 3, + GtalkMessageStanza_MessageType_Error = 4, +}; + +GPBEnumDescriptor *GtalkMessageStanza_MessageType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkMessageStanza_MessageType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_PresenceType + +typedef GPB_ENUM(GtalkPresenceStanza_PresenceType) { + GtalkPresenceStanza_PresenceType_Unavailable = 0, + GtalkPresenceStanza_PresenceType_Subscribe = 1, + GtalkPresenceStanza_PresenceType_Subscribed = 2, + GtalkPresenceStanza_PresenceType_Unsubscribe = 3, + GtalkPresenceStanza_PresenceType_Unsubscribed = 4, + GtalkPresenceStanza_PresenceType_Probe = 5, + GtalkPresenceStanza_PresenceType_Error = 6, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_PresenceType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_PresenceType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_ShowType + +typedef GPB_ENUM(GtalkPresenceStanza_ShowType) { + GtalkPresenceStanza_ShowType_Away = 0, + GtalkPresenceStanza_ShowType_Chat = 1, + GtalkPresenceStanza_ShowType_Dnd = 2, + GtalkPresenceStanza_ShowType_Xa = 3, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_ShowType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_ShowType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_ClientType + +typedef GPB_ENUM(GtalkPresenceStanza_ClientType) { + GtalkPresenceStanza_ClientType_Mobile = 0, + GtalkPresenceStanza_ClientType_Android = 1, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_ClientType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_ClientType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_CapabilitiesFlags + +typedef GPB_ENUM(GtalkPresenceStanza_CapabilitiesFlags) { + GtalkPresenceStanza_CapabilitiesFlags_HasVoiceV1 = 1, + GtalkPresenceStanza_CapabilitiesFlags_HasVideoV1 = 2, + GtalkPresenceStanza_CapabilitiesFlags_HasCameraV1 = 4, + GtalkPresenceStanza_CapabilitiesFlags_HasPmucV1 = 8, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_CapabilitiesFlags_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_CapabilitiesFlags_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkBatchPresenceStanza_Type + +typedef GPB_ENUM(GtalkBatchPresenceStanza_Type) { + GtalkBatchPresenceStanza_Type_Get = 0, + GtalkBatchPresenceStanza_Type_Set = 1, +}; + +GPBEnumDescriptor *GtalkBatchPresenceStanza_Type_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkBatchPresenceStanza_Type_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkIqStanza_IqType + +typedef GPB_ENUM(GtalkIqStanza_IqType) { + GtalkIqStanza_IqType_Get = 0, + GtalkIqStanza_IqType_Set = 1, + GtalkIqStanza_IqType_Result = 2, + GtalkIqStanza_IqType_Error = 3, +}; + +GPBEnumDescriptor *GtalkIqStanza_IqType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkIqStanza_IqType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkClientEvent_Type + +typedef GPB_ENUM(GtalkClientEvent_Type) { + GtalkClientEvent_Type_Unknown = 0, + GtalkClientEvent_Type_DiscardedEvents = 1, + GtalkClientEvent_Type_FailedConnection = 2, + GtalkClientEvent_Type_SuccessfulConnection = 3, + GtalkClientEvent_Type_McsReconnectRequest = 4, + GtalkClientEvent_Type_FailedSocketCreationMcsReconnect = 5, + GtalkClientEvent_Type_McsReconnectLimited = 6, +}; + +GPBEnumDescriptor *GtalkClientEvent_Type_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkClientEvent_Type_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkClientEvent_McsReconnectAction + +typedef GPB_ENUM(GtalkClientEvent_McsReconnectAction) { + GtalkClientEvent_McsReconnectAction_None = 0, + GtalkClientEvent_McsReconnectAction_NotConnected = 1, + GtalkClientEvent_McsReconnectAction_TooSoon = 2, +}; + +GPBEnumDescriptor *GtalkClientEvent_McsReconnectAction_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkClientEvent_McsReconnectAction_IsValidValue(int32_t value); + +#pragma mark - GtalkGtalkCoreRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GtalkGtalkCoreRoot : GPBRootObject +@end + +#pragma mark - GtalkHeartbeatPing + +typedef GPB_ENUM(GtalkHeartbeatPing_FieldNumber) { + GtalkHeartbeatPing_FieldNumber_StreamId = 1, + GtalkHeartbeatPing_FieldNumber_LastStreamIdReceived = 2, + GtalkHeartbeatPing_FieldNumber_Status = 3, + GtalkHeartbeatPing_FieldNumber_CellTower = 4, + GtalkHeartbeatPing_FieldNumber_IntervalMs = 5, +}; + +@interface GtalkHeartbeatPing : GPBMessage + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkHeartbeatAck + +typedef GPB_ENUM(GtalkHeartbeatAck_FieldNumber) { + GtalkHeartbeatAck_FieldNumber_StreamId = 1, + GtalkHeartbeatAck_FieldNumber_LastStreamIdReceived = 2, + GtalkHeartbeatAck_FieldNumber_Status = 3, + GtalkHeartbeatAck_FieldNumber_CellTower = 4, + GtalkHeartbeatAck_FieldNumber_IntervalMs = 5, +}; + +@interface GtalkHeartbeatAck : GPBMessage + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkErrorInfo + +typedef GPB_ENUM(GtalkErrorInfo_FieldNumber) { + GtalkErrorInfo_FieldNumber_Code = 1, + GtalkErrorInfo_FieldNumber_Message = 2, + GtalkErrorInfo_FieldNumber_Type = 3, + GtalkErrorInfo_FieldNumber_Extension = 4, +}; + +@interface GtalkErrorInfo : GPBMessage + + +@property(nonatomic, readwrite) int32_t code; + +@property(nonatomic, readwrite) BOOL hasCode; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *message; +/** Test to see if @c message has been set. */ +@property(nonatomic, readwrite) BOOL hasMessage; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *type; +/** Test to see if @c type has been set. */ +@property(nonatomic, readwrite) BOOL hasType; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkExtension *extension; +/** Test to see if @c extension has been set. */ +@property(nonatomic, readwrite) BOOL hasExtension; + +@end + +#pragma mark - GtalkSetting + +typedef GPB_ENUM(GtalkSetting_FieldNumber) { + GtalkSetting_FieldNumber_Name = 1, + GtalkSetting_FieldNumber_Value = 2, +}; + +@interface GtalkSetting : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; +/** Test to see if @c name has been set. */ +@property(nonatomic, readwrite) BOOL hasName; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +#pragma mark - GtalkHeartbeatStat + +typedef GPB_ENUM(GtalkHeartbeatStat_FieldNumber) { + GtalkHeartbeatStat_FieldNumber_Ip = 1, + GtalkHeartbeatStat_FieldNumber_Timeout = 2, + GtalkHeartbeatStat_FieldNumber_IntervalMs = 3, +}; + +@interface GtalkHeartbeatStat : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ip; +/** Test to see if @c ip has been set. */ +@property(nonatomic, readwrite) BOOL hasIp; + + +@property(nonatomic, readwrite) BOOL timeout; + +@property(nonatomic, readwrite) BOOL hasTimeout; + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkHeartbeatConfig + +typedef GPB_ENUM(GtalkHeartbeatConfig_FieldNumber) { + GtalkHeartbeatConfig_FieldNumber_UploadStat = 1, + GtalkHeartbeatConfig_FieldNumber_Ip = 2, + GtalkHeartbeatConfig_FieldNumber_IntervalMs = 3, +}; + +@interface GtalkHeartbeatConfig : GPBMessage + + +@property(nonatomic, readwrite) BOOL uploadStat; + +@property(nonatomic, readwrite) BOOL hasUploadStat; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ip; +/** Test to see if @c ip has been set. */ +@property(nonatomic, readwrite) BOOL hasIp; + + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkLoginRequest + +typedef GPB_ENUM(GtalkLoginRequest_FieldNumber) { + GtalkLoginRequest_FieldNumber_Id_p = 1, + GtalkLoginRequest_FieldNumber_Domain = 2, + GtalkLoginRequest_FieldNumber_User = 3, + GtalkLoginRequest_FieldNumber_Resource = 4, + GtalkLoginRequest_FieldNumber_AuthToken = 5, + GtalkLoginRequest_FieldNumber_DeviceId = 6, + GtalkLoginRequest_FieldNumber_LastRmqId = 7, + GtalkLoginRequest_FieldNumber_SettingArray = 8, + GtalkLoginRequest_FieldNumber_ReceivedPersistentIdArray = 10, + GtalkLoginRequest_FieldNumber_IncludeStreamIds = 11, + GtalkLoginRequest_FieldNumber_HeartbeatStat = 13, + GtalkLoginRequest_FieldNumber_UseRmq2 = 14, + GtalkLoginRequest_FieldNumber_AccountId = 15, + GtalkLoginRequest_FieldNumber_AuthService = 16, + GtalkLoginRequest_FieldNumber_NetworkType = 17, + GtalkLoginRequest_FieldNumber_Status = 18, + GtalkLoginRequest_FieldNumber_TokenVersionInfo = 19, + GtalkLoginRequest_FieldNumber_CellTower = 20, + GtalkLoginRequest_FieldNumber_GcmStartTimeMs = 21, + GtalkLoginRequest_FieldNumber_ClientEventArray = 22, + GtalkLoginRequest_FieldNumber_OnFallback = 23, + GtalkLoginRequest_FieldNumber_NoPendingUpstream = 24, + GtalkLoginRequest_FieldNumber_ReconnectRequestId = 25, +}; + +@interface GtalkLoginRequest : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *domain; +/** Test to see if @c domain has been set. */ +@property(nonatomic, readwrite) BOOL hasDomain; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *resource; +/** Test to see if @c resource has been set. */ +@property(nonatomic, readwrite) BOOL hasResource; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *authToken; +/** Test to see if @c authToken has been set. */ +@property(nonatomic, readwrite) BOOL hasAuthToken; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *deviceId; +/** Test to see if @c deviceId has been set. */ +@property(nonatomic, readwrite) BOOL hasDeviceId; + + +@property(nonatomic, readwrite) int64_t lastRmqId; + +@property(nonatomic, readwrite) BOOL hasLastRmqId; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *settingArray; +/** The number of items in @c settingArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger settingArray_Count; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *receivedPersistentIdArray; +/** The number of items in @c receivedPersistentIdArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger receivedPersistentIdArray_Count; + + +@property(nonatomic, readwrite) BOOL includeStreamIds; + +@property(nonatomic, readwrite) BOOL hasIncludeStreamIds; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkHeartbeatStat *heartbeatStat; +/** Test to see if @c heartbeatStat has been set. */ +@property(nonatomic, readwrite) BOOL hasHeartbeatStat; + + +@property(nonatomic, readwrite) BOOL useRmq2; + +@property(nonatomic, readwrite) BOOL hasUseRmq2; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; + +@property(nonatomic, readwrite) GtalkLoginRequest_AuthService authService; + +@property(nonatomic, readwrite) BOOL hasAuthService; + +@property(nonatomic, readwrite) int32_t networkType; + +@property(nonatomic, readwrite) BOOL hasNetworkType; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *tokenVersionInfo; +/** Test to see if @c tokenVersionInfo has been set. */ +@property(nonatomic, readwrite) BOOL hasTokenVersionInfo; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) uint64_t gcmStartTimeMs; + +@property(nonatomic, readwrite) BOOL hasGcmStartTimeMs; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *clientEventArray; +/** The number of items in @c clientEventArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger clientEventArray_Count; + + +@property(nonatomic, readwrite) BOOL onFallback; + +@property(nonatomic, readwrite) BOOL hasOnFallback; + +@property(nonatomic, readwrite) BOOL noPendingUpstream; + +@property(nonatomic, readwrite) BOOL hasNoPendingUpstream; + +@property(nonatomic, readwrite) int32_t reconnectRequestId; + +@property(nonatomic, readwrite) BOOL hasReconnectRequestId; +@end + +#pragma mark - GtalkLoginResponse + +typedef GPB_ENUM(GtalkLoginResponse_FieldNumber) { + GtalkLoginResponse_FieldNumber_Id_p = 1, + GtalkLoginResponse_FieldNumber_Jid = 2, + GtalkLoginResponse_FieldNumber_Error = 3, + GtalkLoginResponse_FieldNumber_SettingArray = 4, + GtalkLoginResponse_FieldNumber_StreamId = 5, + GtalkLoginResponse_FieldNumber_LastStreamIdReceived = 6, + GtalkLoginResponse_FieldNumber_HeartbeatConfig = 7, + GtalkLoginResponse_FieldNumber_ServerTimestamp = 8, +}; + +@interface GtalkLoginResponse : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *settingArray; +/** The number of items in @c settingArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger settingArray_Count; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkHeartbeatConfig *heartbeatConfig; +/** Test to see if @c heartbeatConfig has been set. */ +@property(nonatomic, readwrite) BOOL hasHeartbeatConfig; + + +@property(nonatomic, readwrite) int64_t serverTimestamp; + +@property(nonatomic, readwrite) BOOL hasServerTimestamp; +@end + +#pragma mark - GtalkBindAccountRequest + +typedef GPB_ENUM(GtalkBindAccountRequest_FieldNumber) { + GtalkBindAccountRequest_FieldNumber_Id_p = 1, + GtalkBindAccountRequest_FieldNumber_Domain = 2, + GtalkBindAccountRequest_FieldNumber_User = 3, + GtalkBindAccountRequest_FieldNumber_Resource = 4, + GtalkBindAccountRequest_FieldNumber_AuthToken = 5, + GtalkBindAccountRequest_FieldNumber_PersistentId = 6, + GtalkBindAccountRequest_FieldNumber_StreamId = 7, + GtalkBindAccountRequest_FieldNumber_LastStreamIdReceived = 8, + GtalkBindAccountRequest_FieldNumber_AccountId = 9, +}; + +@interface GtalkBindAccountRequest : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *domain; +/** Test to see if @c domain has been set. */ +@property(nonatomic, readwrite) BOOL hasDomain; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *resource; +/** Test to see if @c resource has been set. */ +@property(nonatomic, readwrite) BOOL hasResource; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *authToken; +/** Test to see if @c authToken has been set. */ +@property(nonatomic, readwrite) BOOL hasAuthToken; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; +@end + +#pragma mark - GtalkBindAccountResponse + +typedef GPB_ENUM(GtalkBindAccountResponse_FieldNumber) { + GtalkBindAccountResponse_FieldNumber_Id_p = 1, + GtalkBindAccountResponse_FieldNumber_Jid = 2, + GtalkBindAccountResponse_FieldNumber_Error = 3, + GtalkBindAccountResponse_FieldNumber_StreamId = 4, + GtalkBindAccountResponse_FieldNumber_LastStreamIdReceived = 5, +}; + +@interface GtalkBindAccountResponse : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; +@end + +#pragma mark - GtalkStreamErrorStanza + +typedef GPB_ENUM(GtalkStreamErrorStanza_FieldNumber) { + GtalkStreamErrorStanza_FieldNumber_Type = 1, + GtalkStreamErrorStanza_FieldNumber_Text = 2, +}; + +@interface GtalkStreamErrorStanza : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *type; +/** Test to see if @c type has been set. */ +@property(nonatomic, readwrite) BOOL hasType; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *text; +/** Test to see if @c text has been set. */ +@property(nonatomic, readwrite) BOOL hasText; + +@end + +#pragma mark - GtalkClose + +@interface GtalkClose : GPBMessage + +@end + +#pragma mark - GtalkExtension + +typedef GPB_ENUM(GtalkExtension_FieldNumber) { + GtalkExtension_FieldNumber_Id_p = 1, + GtalkExtension_FieldNumber_Data_p = 2, +}; + +@interface GtalkExtension : GPBMessage + + +@property(nonatomic, readwrite) int32_t id_p; + +@property(nonatomic, readwrite) BOOL hasId_p; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *data_p; +/** Test to see if @c data_p has been set. */ +@property(nonatomic, readwrite) BOOL hasData_p; + +@end + +#pragma mark - GtalkMessageStanza + +typedef GPB_ENUM(GtalkMessageStanza_FieldNumber) { + GtalkMessageStanza_FieldNumber_RmqId = 1, + GtalkMessageStanza_FieldNumber_Type = 2, + GtalkMessageStanza_FieldNumber_Id_p = 3, + GtalkMessageStanza_FieldNumber_From = 4, + GtalkMessageStanza_FieldNumber_To = 5, + GtalkMessageStanza_FieldNumber_Subject = 6, + GtalkMessageStanza_FieldNumber_Body = 7, + GtalkMessageStanza_FieldNumber_Thread = 8, + GtalkMessageStanza_FieldNumber_Error = 9, + GtalkMessageStanza_FieldNumber_ExtensionArray = 10, + GtalkMessageStanza_FieldNumber_Nosave = 11, + GtalkMessageStanza_FieldNumber_Timestamp = 12, + GtalkMessageStanza_FieldNumber_PersistentId = 13, + GtalkMessageStanza_FieldNumber_StreamId = 14, + GtalkMessageStanza_FieldNumber_LastStreamIdReceived = 15, + GtalkMessageStanza_FieldNumber_Read = 16, + GtalkMessageStanza_FieldNumber_AccountId = 17, +}; + +@interface GtalkMessageStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite) GtalkMessageStanza_MessageType type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *subject; +/** Test to see if @c subject has been set. */ +@property(nonatomic, readwrite) BOOL hasSubject; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *body; +/** Test to see if @c body has been set. */ +@property(nonatomic, readwrite) BOOL hasBody; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *thread; +/** Test to see if @c thread has been set. */ +@property(nonatomic, readwrite) BOOL hasThread; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray; +/** The number of items in @c extensionArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger extensionArray_Count; + + +@property(nonatomic, readwrite) BOOL nosave; + +@property(nonatomic, readwrite) BOOL hasNosave; + +@property(nonatomic, readwrite) int64_t timestamp; + +@property(nonatomic, readwrite) BOOL hasTimestamp; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL read; + +@property(nonatomic, readwrite) BOOL hasRead; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; +@end + +#pragma mark - GtalkPresenceStanza + +typedef GPB_ENUM(GtalkPresenceStanza_FieldNumber) { + GtalkPresenceStanza_FieldNumber_RmqId = 1, + GtalkPresenceStanza_FieldNumber_Type = 2, + GtalkPresenceStanza_FieldNumber_Id_p = 3, + GtalkPresenceStanza_FieldNumber_From = 4, + GtalkPresenceStanza_FieldNumber_To = 5, + GtalkPresenceStanza_FieldNumber_Show = 6, + GtalkPresenceStanza_FieldNumber_Status = 7, + GtalkPresenceStanza_FieldNumber_Priority = 8, + GtalkPresenceStanza_FieldNumber_Error = 9, + GtalkPresenceStanza_FieldNumber_ExtensionArray = 10, + GtalkPresenceStanza_FieldNumber_Client = 11, + GtalkPresenceStanza_FieldNumber_AvatarHash = 12, + GtalkPresenceStanza_FieldNumber_PersistentId = 13, + GtalkPresenceStanza_FieldNumber_StreamId = 14, + GtalkPresenceStanza_FieldNumber_LastStreamIdReceived = 15, + GtalkPresenceStanza_FieldNumber_CapabilitiesFlags = 16, + GtalkPresenceStanza_FieldNumber_AccountId = 17, +}; + +@interface GtalkPresenceStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite) GtalkPresenceStanza_PresenceType type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite) GtalkPresenceStanza_ShowType show; + +@property(nonatomic, readwrite) BOOL hasShow; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *status; +/** Test to see if @c status has been set. */ +@property(nonatomic, readwrite) BOOL hasStatus; + + +@property(nonatomic, readwrite) int32_t priority; + +@property(nonatomic, readwrite) BOOL hasPriority; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray; +/** The number of items in @c extensionArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger extensionArray_Count; + + +@property(nonatomic, readwrite) GtalkPresenceStanza_ClientType client; + +@property(nonatomic, readwrite) BOOL hasClient; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *avatarHash; +/** Test to see if @c avatarHash has been set. */ +@property(nonatomic, readwrite) BOOL hasAvatarHash; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int32_t capabilitiesFlags; + +@property(nonatomic, readwrite) BOOL hasCapabilitiesFlags; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; +@end + +#pragma mark - GtalkBatchPresenceStanza + +typedef GPB_ENUM(GtalkBatchPresenceStanza_FieldNumber) { + GtalkBatchPresenceStanza_FieldNumber_Id_p = 1, + GtalkBatchPresenceStanza_FieldNumber_To = 2, + GtalkBatchPresenceStanza_FieldNumber_PresenceArray = 3, + GtalkBatchPresenceStanza_FieldNumber_PersistentId = 4, + GtalkBatchPresenceStanza_FieldNumber_StreamId = 5, + GtalkBatchPresenceStanza_FieldNumber_LastStreamIdReceived = 6, + GtalkBatchPresenceStanza_FieldNumber_AccountId = 7, + GtalkBatchPresenceStanza_FieldNumber_Type = 8, + GtalkBatchPresenceStanza_FieldNumber_Error = 9, +}; + +@interface GtalkBatchPresenceStanza : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *presenceArray; +/** The number of items in @c presenceArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger presenceArray_Count; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; + +@property(nonatomic, readwrite) GtalkBatchPresenceStanza_Type type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + +@end + +#pragma mark - GtalkIqStanza + +typedef GPB_ENUM(GtalkIqStanza_FieldNumber) { + GtalkIqStanza_FieldNumber_RmqId = 1, + GtalkIqStanza_FieldNumber_Type = 2, + GtalkIqStanza_FieldNumber_Id_p = 3, + GtalkIqStanza_FieldNumber_From = 4, + GtalkIqStanza_FieldNumber_To = 5, + GtalkIqStanza_FieldNumber_Error = 6, + GtalkIqStanza_FieldNumber_Extension = 7, + GtalkIqStanza_FieldNumber_PersistentId = 8, + GtalkIqStanza_FieldNumber_StreamId = 9, + GtalkIqStanza_FieldNumber_LastStreamIdReceived = 10, + GtalkIqStanza_FieldNumber_AccountId = 11, + GtalkIqStanza_FieldNumber_Status = 12, +}; + +@interface GtalkIqStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite) GtalkIqStanza_IqType type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkExtension *extension; +/** Test to see if @c extension has been set. */ +@property(nonatomic, readwrite) BOOL hasExtension; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; +@end + +#pragma mark - GtalkAppData + +typedef GPB_ENUM(GtalkAppData_FieldNumber) { + GtalkAppData_FieldNumber_Key = 1, + GtalkAppData_FieldNumber_Value = 2, +}; + +@interface GtalkAppData : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *key; +/** Test to see if @c key has been set. */ +@property(nonatomic, readwrite) BOOL hasKey; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +#pragma mark - GtalkDataMessageStanza + +typedef GPB_ENUM(GtalkDataMessageStanza_FieldNumber) { + GtalkDataMessageStanza_FieldNumber_RmqId = 1, + GtalkDataMessageStanza_FieldNumber_Id_p = 2, + GtalkDataMessageStanza_FieldNumber_From = 3, + GtalkDataMessageStanza_FieldNumber_To = 4, + GtalkDataMessageStanza_FieldNumber_Category = 5, + GtalkDataMessageStanza_FieldNumber_Token = 6, + GtalkDataMessageStanza_FieldNumber_AppDataArray = 7, + GtalkDataMessageStanza_FieldNumber_FromTrustedServer = 8, + GtalkDataMessageStanza_FieldNumber_PersistentId = 9, + GtalkDataMessageStanza_FieldNumber_StreamId = 10, + GtalkDataMessageStanza_FieldNumber_LastStreamIdReceived = 11, + GtalkDataMessageStanza_FieldNumber_Permission = 12, + GtalkDataMessageStanza_FieldNumber_RegId = 13, + GtalkDataMessageStanza_FieldNumber_PkgSignature = 14, + GtalkDataMessageStanza_FieldNumber_ClientId = 15, + GtalkDataMessageStanza_FieldNumber_DeviceUserId = 16, + GtalkDataMessageStanza_FieldNumber_Ttl = 17, + GtalkDataMessageStanza_FieldNumber_Sent = 18, + GtalkDataMessageStanza_FieldNumber_Queued = 19, + GtalkDataMessageStanza_FieldNumber_Status = 20, + GtalkDataMessageStanza_FieldNumber_RawData = 21, + GtalkDataMessageStanza_FieldNumber_MaxDelay = 22, + GtalkDataMessageStanza_FieldNumber_ActualDelay = 23, + GtalkDataMessageStanza_FieldNumber_ImmediateAck = 24, + GtalkDataMessageStanza_FieldNumber_DeliveryReceiptRequested = 25, + GtalkDataMessageStanza_FieldNumber_ExternalMessageId = 26, + GtalkDataMessageStanza_FieldNumber_Flags = 27, + GtalkDataMessageStanza_FieldNumber_CellTower = 28, + GtalkDataMessageStanza_FieldNumber_Priority = 29, +}; + +@interface GtalkDataMessageStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *category; +/** Test to see if @c category has been set. */ +@property(nonatomic, readwrite) BOOL hasCategory; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *token; +/** Test to see if @c token has been set. */ +@property(nonatomic, readwrite) BOOL hasToken; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *appDataArray; +/** The number of items in @c appDataArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger appDataArray_Count; + + +@property(nonatomic, readwrite) BOOL fromTrustedServer; + +@property(nonatomic, readwrite) BOOL hasFromTrustedServer; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *permission; +/** Test to see if @c permission has been set. */ +@property(nonatomic, readwrite) BOOL hasPermission; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *regId; +/** Test to see if @c regId has been set. */ +@property(nonatomic, readwrite) BOOL hasRegId; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *pkgSignature; +/** Test to see if @c pkgSignature has been set. */ +@property(nonatomic, readwrite) BOOL hasPkgSignature; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *clientId; +/** Test to see if @c clientId has been set. */ +@property(nonatomic, readwrite) BOOL hasClientId; + + +@property(nonatomic, readwrite) int64_t deviceUserId; + +@property(nonatomic, readwrite) BOOL hasDeviceUserId; + +@property(nonatomic, readwrite) int32_t ttl; + +@property(nonatomic, readwrite) BOOL hasTtl; + +@property(nonatomic, readwrite) int64_t sent; + +@property(nonatomic, readwrite) BOOL hasSent; + +@property(nonatomic, readwrite) int32_t queued; + +@property(nonatomic, readwrite) BOOL hasQueued; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *rawData; +/** Test to see if @c rawData has been set. */ +@property(nonatomic, readwrite) BOOL hasRawData; + + +@property(nonatomic, readwrite) int32_t maxDelay; + +@property(nonatomic, readwrite) BOOL hasMaxDelay; + +@property(nonatomic, readwrite) int32_t actualDelay; + +@property(nonatomic, readwrite) BOOL hasActualDelay; + +@property(nonatomic, readwrite) BOOL immediateAck; + +@property(nonatomic, readwrite) BOOL hasImmediateAck; + +@property(nonatomic, readwrite) BOOL deliveryReceiptRequested; + +@property(nonatomic, readwrite) BOOL hasDeliveryReceiptRequested; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *externalMessageId; +/** Test to see if @c externalMessageId has been set. */ +@property(nonatomic, readwrite) BOOL hasExternalMessageId; + + +@property(nonatomic, readwrite) int64_t flags; + +@property(nonatomic, readwrite) BOOL hasFlags; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) int32_t priority; + +@property(nonatomic, readwrite) BOOL hasPriority; +@end + +#pragma mark - GtalkTalkMetadata + +typedef GPB_ENUM(GtalkTalkMetadata_FieldNumber) { + GtalkTalkMetadata_FieldNumber_Foreground = 1, +}; + +@interface GtalkTalkMetadata : GPBMessage + + +@property(nonatomic, readwrite) BOOL foreground; + +@property(nonatomic, readwrite) BOOL hasForeground; +@end + +#pragma mark - GtalkCellTower + +typedef GPB_ENUM(GtalkCellTower_FieldNumber) { + GtalkCellTower_FieldNumber_Id_p = 1, + GtalkCellTower_FieldNumber_KnownCongestionStatus = 2, +}; + +DEPRECATED_ATTRIBUTE +@interface GtalkCellTower : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite) int32_t knownCongestionStatus; + +@property(nonatomic, readwrite) BOOL hasKnownCongestionStatus; +@end + +#pragma mark - GtalkClientEvent + +typedef GPB_ENUM(GtalkClientEvent_FieldNumber) { + GtalkClientEvent_FieldNumber_Type = 1, + GtalkClientEvent_FieldNumber_NumberDiscardedEvents = 100, + GtalkClientEvent_FieldNumber_NetworkType = 200, + GtalkClientEvent_FieldNumber_NetworkPort = 201, + GtalkClientEvent_FieldNumber_TimeConnectionStartedMs = 202, + GtalkClientEvent_FieldNumber_TimeConnectionEndedMs = 203, + GtalkClientEvent_FieldNumber_ErrorCode = 204, + GtalkClientEvent_FieldNumber_TimeConnectionEstablishedMs = 300, + GtalkClientEvent_FieldNumber_McsReconnectAction = 400, +}; + +@interface GtalkClientEvent : GPBMessage + + +@property(nonatomic, readwrite) GtalkClientEvent_Type type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite) uint32_t numberDiscardedEvents; + +@property(nonatomic, readwrite) BOOL hasNumberDiscardedEvents; + +@property(nonatomic, readwrite) int32_t networkType; + +@property(nonatomic, readwrite) BOOL hasNetworkType; + +@property(nonatomic, readwrite) int32_t networkPort; + +@property(nonatomic, readwrite) BOOL hasNetworkPort; + +@property(nonatomic, readwrite) uint64_t timeConnectionStartedMs; + +@property(nonatomic, readwrite) BOOL hasTimeConnectionStartedMs; + +@property(nonatomic, readwrite) uint64_t timeConnectionEndedMs; + +@property(nonatomic, readwrite) BOOL hasTimeConnectionEndedMs; + +@property(nonatomic, readwrite) int32_t errorCode; + +@property(nonatomic, readwrite) BOOL hasErrorCode; + +@property(nonatomic, readwrite) uint64_t timeConnectionEstablishedMs; + +@property(nonatomic, readwrite) BOOL hasTimeConnectionEstablishedMs; + +@property(nonatomic, readwrite) GtalkClientEvent_McsReconnectAction mcsReconnectAction; + +@property(nonatomic, readwrite) BOOL hasMcsReconnectAction; +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.m new file mode 100644 index 0000000..06c9134 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.m @@ -0,0 +1,3017 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_core.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + + #import "GtalkCore.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GtalkGtalkCoreRoot + +@implementation GtalkGtalkCoreRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GtalkGtalkCoreRoot_FileDescriptor + +static GPBFileDescriptor *GtalkGtalkCoreRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"mobilegtalk" + objcPrefix:@"Gtalk" + syntax:GPBFileSyntaxProto2]; + } + return descriptor; +} + +#pragma mark - GtalkHeartbeatPing + +@implementation GtalkHeartbeatPing + +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasStatus, status; +@dynamic hasCellTower, cellTower; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatPing__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t intervalMs; + GtalkCellTower *cellTower; + int64_t status; +} GtalkHeartbeatPing__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_StreamId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_LastStreamIdReceived, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_Status, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkHeartbeatPing_FieldNumber_CellTower, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_IntervalMs, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, intervalMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatPing class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatPing__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkHeartbeatAck + +@implementation GtalkHeartbeatAck + +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasStatus, status; +@dynamic hasCellTower, cellTower; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatAck__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t intervalMs; + GtalkCellTower *cellTower; + int64_t status; +} GtalkHeartbeatAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_StreamId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_LastStreamIdReceived, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_Status, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkHeartbeatAck_FieldNumber_CellTower, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_IntervalMs, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, intervalMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatAck class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkErrorInfo + +@implementation GtalkErrorInfo + +@dynamic hasCode, code; +@dynamic hasMessage, message; +@dynamic hasType, type; +@dynamic hasExtension, extension; + +typedef struct GtalkErrorInfo__storage_ { + uint32_t _has_storage_[1]; + int32_t code; + NSString *message; + NSString *type; + GtalkExtension *extension; +} GtalkErrorInfo__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "code", + .dataTypeSpecific.className = NULL, + .number = GtalkErrorInfo_FieldNumber_Code, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, code), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt32, + }, + { + .name = "message", + .dataTypeSpecific.className = NULL, + .number = GtalkErrorInfo_FieldNumber_Message, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, message), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "type", + .dataTypeSpecific.className = NULL, + .number = GtalkErrorInfo_FieldNumber_Type, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, type), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "extension", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkErrorInfo_FieldNumber_Extension, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, extension), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkErrorInfo class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkErrorInfo__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkSetting + +@implementation GtalkSetting + +@dynamic hasName, name; +@dynamic hasValue, value; + +typedef struct GtalkSetting__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + NSString *value; +} GtalkSetting__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GtalkSetting_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkSetting__storage_, name), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GtalkSetting_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkSetting__storage_, value), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSetting class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSetting__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkHeartbeatStat + +@implementation GtalkHeartbeatStat + +@dynamic hasIp, ip; +@dynamic hasTimeout, timeout; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatStat__storage_ { + uint32_t _has_storage_[1]; + int32_t intervalMs; + NSString *ip; +} GtalkHeartbeatStat__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "ip", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatStat_FieldNumber_Ip, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkHeartbeatStat__storage_, ip), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "timeout", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatStat_FieldNumber_Timeout, + .hasIndex = 1, + .offset = 2, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatStat_FieldNumber_IntervalMs, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatStat__storage_, intervalMs), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatStat class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatStat__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkHeartbeatConfig + +@implementation GtalkHeartbeatConfig + +@dynamic hasUploadStat, uploadStat; +@dynamic hasIp, ip; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatConfig__storage_ { + uint32_t _has_storage_[1]; + int32_t intervalMs; + NSString *ip; +} GtalkHeartbeatConfig__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "uploadStat", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatConfig_FieldNumber_UploadStat, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "ip", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatConfig_FieldNumber_Ip, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkHeartbeatConfig__storage_, ip), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatConfig_FieldNumber_IntervalMs, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatConfig__storage_, intervalMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatConfig class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatConfig__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkLoginRequest + +@implementation GtalkLoginRequest + +@dynamic hasId_p, id_p; +@dynamic hasDomain, domain; +@dynamic hasUser, user; +@dynamic hasResource, resource; +@dynamic hasAuthToken, authToken; +@dynamic hasDeviceId, deviceId; +@dynamic hasLastRmqId, lastRmqId; +@dynamic settingArray, settingArray_Count; +@dynamic receivedPersistentIdArray, receivedPersistentIdArray_Count; +@dynamic hasIncludeStreamIds, includeStreamIds; +@dynamic hasHeartbeatStat, heartbeatStat; +@dynamic hasUseRmq2, useRmq2; +@dynamic hasAccountId, accountId; +@dynamic hasAuthService, authService; +@dynamic hasNetworkType, networkType; +@dynamic hasStatus, status; +@dynamic hasTokenVersionInfo, tokenVersionInfo; +@dynamic hasCellTower, cellTower; +@dynamic hasGcmStartTimeMs, gcmStartTimeMs; +@dynamic clientEventArray, clientEventArray_Count; +@dynamic hasOnFallback, onFallback; +@dynamic hasNoPendingUpstream, noPendingUpstream; +@dynamic hasReconnectRequestId, reconnectRequestId; + +typedef struct GtalkLoginRequest__storage_ { + uint32_t _has_storage_[1]; + GtalkLoginRequest_AuthService authService; + int32_t networkType; + int32_t reconnectRequestId; + NSString *id_p; + NSString *domain; + NSString *user; + NSString *resource; + NSString *authToken; + NSString *deviceId; + NSMutableArray *settingArray; + NSMutableArray *receivedPersistentIdArray; + GtalkHeartbeatStat *heartbeatStat; + NSString *tokenVersionInfo; + GtalkCellTower *cellTower; + NSMutableArray *clientEventArray; + int64_t lastRmqId; + int64_t accountId; + int64_t status; + uint64_t gcmStartTimeMs; +} GtalkLoginRequest__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "domain", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Domain, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, domain), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_User, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "resource", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Resource, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, resource), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "authToken", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_AuthToken, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, authToken), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "deviceId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_DeviceId, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, deviceId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "lastRmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_LastRmqId, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, lastRmqId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "settingArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkSetting), + .number = GtalkLoginRequest_FieldNumber_SettingArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, settingArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "receivedPersistentIdArray", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_ReceivedPersistentIdArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, receivedPersistentIdArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "includeStreamIds", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_IncludeStreamIds, + .hasIndex = 7, + .offset = 8, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "heartbeatStat", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkHeartbeatStat), + .number = GtalkLoginRequest_FieldNumber_HeartbeatStat, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, heartbeatStat), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "useRmq2", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_UseRmq2, + .hasIndex = 10, + .offset = 11, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_AccountId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "authService", + .dataTypeSpecific.enumDescFunc = GtalkLoginRequest_AuthService_EnumDescriptor, + .number = GtalkLoginRequest_FieldNumber_AuthService, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, authService), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "networkType", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_NetworkType, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, networkType), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Status, + .hasIndex = 15, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "tokenVersionInfo", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_TokenVersionInfo, + .hasIndex = 16, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, tokenVersionInfo), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkLoginRequest_FieldNumber_CellTower, + .hasIndex = 17, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "gcmStartTimeMs", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_GcmStartTimeMs, + .hasIndex = 18, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, gcmStartTimeMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "clientEventArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkClientEvent), + .number = GtalkLoginRequest_FieldNumber_ClientEventArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, clientEventArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "onFallback", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_OnFallback, + .hasIndex = 19, + .offset = 20, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "noPendingUpstream", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_NoPendingUpstream, + .hasIndex = 21, + .offset = 22, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "reconnectRequestId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_ReconnectRequestId, + .hasIndex = 23, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, reconnectRequestId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkLoginRequest class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkLoginRequest__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkLoginRequest_AuthService + +GPBEnumDescriptor *GtalkLoginRequest_AuthService_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Mail\000AndroidCloudToDeviceMessage\000Android" + "Id\000"; + static const int32_t values[] = { + GtalkLoginRequest_AuthService_Mail, + GtalkLoginRequest_AuthService_AndroidCloudToDeviceMessage, + GtalkLoginRequest_AuthService_AndroidId, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkLoginRequest_AuthService) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkLoginRequest_AuthService_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkLoginRequest_AuthService_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkLoginRequest_AuthService_Mail: + case GtalkLoginRequest_AuthService_AndroidCloudToDeviceMessage: + case GtalkLoginRequest_AuthService_AndroidId: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkLoginResponse + +@implementation GtalkLoginResponse + +@dynamic hasId_p, id_p; +@dynamic hasJid, jid; +@dynamic hasError, error; +@dynamic settingArray, settingArray_Count; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasHeartbeatConfig, heartbeatConfig; +@dynamic hasServerTimestamp, serverTimestamp; + +typedef struct GtalkLoginResponse__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *jid; + GtalkErrorInfo *error; + NSMutableArray *settingArray; + GtalkHeartbeatConfig *heartbeatConfig; + int64_t serverTimestamp; +} GtalkLoginResponse__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_Jid, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, jid), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkLoginResponse_FieldNumber_Error, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "settingArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkSetting), + .number = GtalkLoginResponse_FieldNumber_SettingArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, settingArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_StreamId, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_LastStreamIdReceived, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "heartbeatConfig", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkHeartbeatConfig), + .number = GtalkLoginResponse_FieldNumber_HeartbeatConfig, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, heartbeatConfig), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "serverTimestamp", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_ServerTimestamp, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, serverTimestamp), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkLoginResponse class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkLoginResponse__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkBindAccountRequest + +@implementation GtalkBindAccountRequest + +@dynamic hasId_p, id_p; +@dynamic hasDomain, domain; +@dynamic hasUser, user; +@dynamic hasResource, resource; +@dynamic hasAuthToken, authToken; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasAccountId, accountId; + +typedef struct GtalkBindAccountRequest__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *domain; + NSString *user; + NSString *resource; + NSString *authToken; + NSString *persistentId; + int64_t accountId; +} GtalkBindAccountRequest__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "domain", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_Domain, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, domain), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_User, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "resource", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_Resource, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, resource), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "authToken", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_AuthToken, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, authToken), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_PersistentId, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_StreamId, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_LastStreamIdReceived, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_AccountId, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkBindAccountRequest class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkBindAccountRequest__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkBindAccountResponse + +@implementation GtalkBindAccountResponse + +@dynamic hasId_p, id_p; +@dynamic hasJid, jid; +@dynamic hasError, error; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; + +typedef struct GtalkBindAccountResponse__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *jid; + GtalkErrorInfo *error; +} GtalkBindAccountResponse__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_Jid, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, jid), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkBindAccountResponse_FieldNumber_Error, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_StreamId, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_LastStreamIdReceived, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkBindAccountResponse class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkBindAccountResponse__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkStreamErrorStanza + +@implementation GtalkStreamErrorStanza + +@dynamic hasType, type; +@dynamic hasText, text; + +typedef struct GtalkStreamErrorStanza__storage_ { + uint32_t _has_storage_[1]; + NSString *type; + NSString *text; +} GtalkStreamErrorStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "type", + .dataTypeSpecific.className = NULL, + .number = GtalkStreamErrorStanza_FieldNumber_Type, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkStreamErrorStanza__storage_, type), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "text", + .dataTypeSpecific.className = NULL, + .number = GtalkStreamErrorStanza_FieldNumber_Text, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkStreamErrorStanza__storage_, text), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkStreamErrorStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkStreamErrorStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkClose + +@implementation GtalkClose + + +typedef struct GtalkClose__storage_ { + uint32_t _has_storage_[1]; +} GtalkClose__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkClose class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GtalkClose__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkExtension + +@implementation GtalkExtension + +@dynamic hasId_p, id_p; +@dynamic hasData_p, data_p; + +typedef struct GtalkExtension__storage_ { + uint32_t _has_storage_[1]; + int32_t id_p; + NSString *data_p; +} GtalkExtension__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkExtension_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkExtension__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt32, + }, + { + .name = "data_p", + .dataTypeSpecific.className = NULL, + .number = GtalkExtension_FieldNumber_Data_p, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkExtension__storage_, data_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkExtension class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkExtension__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkMessageStanza + +@implementation GtalkMessageStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasType, type; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasSubject, subject; +@dynamic hasBody, body; +@dynamic hasThread, thread; +@dynamic hasError, error; +@dynamic extensionArray, extensionArray_Count; +@dynamic hasNosave, nosave; +@dynamic hasTimestamp, timestamp; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasRead, read; +@dynamic hasAccountId, accountId; + +typedef struct GtalkMessageStanza__storage_ { + uint32_t _has_storage_[1]; + GtalkMessageStanza_MessageType type; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *from; + NSString *to; + NSString *subject; + NSString *body; + NSString *thread; + GtalkErrorInfo *error; + NSMutableArray *extensionArray; + NSString *persistentId; + int64_t rmqId; + int64_t timestamp; + int64_t accountId; +} GtalkMessageStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, rmqId), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkMessageStanza_MessageType_EnumDescriptor, + .number = GtalkMessageStanza_FieldNumber_Type, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Id_p, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_From, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, from), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_To, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "subject", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Subject, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, subject), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "body", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Body, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, body), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "thread", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Thread, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, thread), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkMessageStanza_FieldNumber_Error, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "extensionArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkMessageStanza_FieldNumber_ExtensionArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, extensionArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "nosave", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Nosave, + .hasIndex = 9, + .offset = 10, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "timestamp", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Timestamp, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, timestamp), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_PersistentId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_StreamId, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "read", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Read, + .hasIndex = 15, + .offset = 16, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_AccountId, + .hasIndex = 17, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkMessageStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkMessageStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\005\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkMessageStanza_MessageType + +GPBEnumDescriptor *GtalkMessageStanza_MessageType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Normal\000Chat\000Groupchat\000Headline\000Error\000"; + static const int32_t values[] = { + GtalkMessageStanza_MessageType_Normal, + GtalkMessageStanza_MessageType_Chat, + GtalkMessageStanza_MessageType_Groupchat, + GtalkMessageStanza_MessageType_Headline, + GtalkMessageStanza_MessageType_Error, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkMessageStanza_MessageType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkMessageStanza_MessageType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkMessageStanza_MessageType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkMessageStanza_MessageType_Normal: + case GtalkMessageStanza_MessageType_Chat: + case GtalkMessageStanza_MessageType_Groupchat: + case GtalkMessageStanza_MessageType_Headline: + case GtalkMessageStanza_MessageType_Error: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkPresenceStanza + +@implementation GtalkPresenceStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasType, type; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasShow, show; +@dynamic hasStatus, status; +@dynamic hasPriority, priority; +@dynamic hasError, error; +@dynamic extensionArray, extensionArray_Count; +@dynamic hasClient, client; +@dynamic hasAvatarHash, avatarHash; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasCapabilitiesFlags, capabilitiesFlags; +@dynamic hasAccountId, accountId; + +typedef struct GtalkPresenceStanza__storage_ { + uint32_t _has_storage_[1]; + GtalkPresenceStanza_PresenceType type; + GtalkPresenceStanza_ShowType show; + int32_t priority; + GtalkPresenceStanza_ClientType client; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t capabilitiesFlags; + NSString *id_p; + NSString *from; + NSString *to; + NSString *status; + GtalkErrorInfo *error; + NSMutableArray *extensionArray; + NSString *avatarHash; + NSString *persistentId; + int64_t rmqId; + int64_t accountId; +} GtalkPresenceStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, rmqId), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkPresenceStanza_PresenceType_EnumDescriptor, + .number = GtalkPresenceStanza_FieldNumber_Type, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_Id_p, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_From, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, from), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_To, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "show", + .dataTypeSpecific.enumDescFunc = GtalkPresenceStanza_ShowType_EnumDescriptor, + .number = GtalkPresenceStanza_FieldNumber_Show, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, show), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_Status, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "priority", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_Priority, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, priority), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkPresenceStanza_FieldNumber_Error, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "extensionArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkPresenceStanza_FieldNumber_ExtensionArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, extensionArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "client", + .dataTypeSpecific.enumDescFunc = GtalkPresenceStanza_ClientType_EnumDescriptor, + .number = GtalkPresenceStanza_FieldNumber_Client, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, client), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "avatarHash", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_AvatarHash, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, avatarHash), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_PersistentId, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_StreamId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "capabilitiesFlags", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_CapabilitiesFlags, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, capabilitiesFlags), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_AccountId, + .hasIndex = 15, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkPresenceStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkPresenceStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\005\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkPresenceStanza_PresenceType + +GPBEnumDescriptor *GtalkPresenceStanza_PresenceType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Unavailable\000Subscribe\000Subscribed\000Unsubsc" + "ribe\000Unsubscribed\000Probe\000Error\000"; + static const int32_t values[] = { + GtalkPresenceStanza_PresenceType_Unavailable, + GtalkPresenceStanza_PresenceType_Subscribe, + GtalkPresenceStanza_PresenceType_Subscribed, + GtalkPresenceStanza_PresenceType_Unsubscribe, + GtalkPresenceStanza_PresenceType_Unsubscribed, + GtalkPresenceStanza_PresenceType_Probe, + GtalkPresenceStanza_PresenceType_Error, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_PresenceType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_PresenceType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_PresenceType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_PresenceType_Unavailable: + case GtalkPresenceStanza_PresenceType_Subscribe: + case GtalkPresenceStanza_PresenceType_Subscribed: + case GtalkPresenceStanza_PresenceType_Unsubscribe: + case GtalkPresenceStanza_PresenceType_Unsubscribed: + case GtalkPresenceStanza_PresenceType_Probe: + case GtalkPresenceStanza_PresenceType_Error: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkPresenceStanza_ShowType + +GPBEnumDescriptor *GtalkPresenceStanza_ShowType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Away\000Chat\000Dnd\000Xa\000"; + static const int32_t values[] = { + GtalkPresenceStanza_ShowType_Away, + GtalkPresenceStanza_ShowType_Chat, + GtalkPresenceStanza_ShowType_Dnd, + GtalkPresenceStanza_ShowType_Xa, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_ShowType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_ShowType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_ShowType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_ShowType_Away: + case GtalkPresenceStanza_ShowType_Chat: + case GtalkPresenceStanza_ShowType_Dnd: + case GtalkPresenceStanza_ShowType_Xa: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkPresenceStanza_ClientType + +GPBEnumDescriptor *GtalkPresenceStanza_ClientType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Mobile\000Android\000"; + static const int32_t values[] = { + GtalkPresenceStanza_ClientType_Mobile, + GtalkPresenceStanza_ClientType_Android, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_ClientType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_ClientType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_ClientType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_ClientType_Mobile: + case GtalkPresenceStanza_ClientType_Android: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkPresenceStanza_CapabilitiesFlags + +GPBEnumDescriptor *GtalkPresenceStanza_CapabilitiesFlags_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "HasVoiceV1\000HasVideoV1\000HasCameraV1\000HasPmu" + "cV1\000"; + static const int32_t values[] = { + GtalkPresenceStanza_CapabilitiesFlags_HasVoiceV1, + GtalkPresenceStanza_CapabilitiesFlags_HasVideoV1, + GtalkPresenceStanza_CapabilitiesFlags_HasCameraV1, + GtalkPresenceStanza_CapabilitiesFlags_HasPmucV1, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_CapabilitiesFlags) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_CapabilitiesFlags_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_CapabilitiesFlags_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_CapabilitiesFlags_HasVoiceV1: + case GtalkPresenceStanza_CapabilitiesFlags_HasVideoV1: + case GtalkPresenceStanza_CapabilitiesFlags_HasCameraV1: + case GtalkPresenceStanza_CapabilitiesFlags_HasPmucV1: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkBatchPresenceStanza + +@implementation GtalkBatchPresenceStanza + +@dynamic hasId_p, id_p; +@dynamic hasTo, to; +@dynamic presenceArray, presenceArray_Count; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasAccountId, accountId; +@dynamic hasType, type; +@dynamic hasError, error; + +typedef struct GtalkBatchPresenceStanza__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + GtalkBatchPresenceStanza_Type type; + NSString *id_p; + NSString *to; + NSMutableArray *presenceArray; + NSString *persistentId; + GtalkErrorInfo *error; + int64_t accountId; +} GtalkBatchPresenceStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_To, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "presenceArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkPresenceStanza), + .number = GtalkBatchPresenceStanza_FieldNumber_PresenceArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, presenceArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_PersistentId, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_StreamId, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_AccountId, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkBatchPresenceStanza_Type_EnumDescriptor, + .number = GtalkBatchPresenceStanza_FieldNumber_Type, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkBatchPresenceStanza_FieldNumber_Error, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkBatchPresenceStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkBatchPresenceStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkBatchPresenceStanza_Type + +GPBEnumDescriptor *GtalkBatchPresenceStanza_Type_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Get\000Set\000"; + static const int32_t values[] = { + GtalkBatchPresenceStanza_Type_Get, + GtalkBatchPresenceStanza_Type_Set, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkBatchPresenceStanza_Type) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkBatchPresenceStanza_Type_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkBatchPresenceStanza_Type_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkBatchPresenceStanza_Type_Get: + case GtalkBatchPresenceStanza_Type_Set: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkIqStanza + +@implementation GtalkIqStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasType, type; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasError, error; +@dynamic hasExtension, extension; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasAccountId, accountId; +@dynamic hasStatus, status; + +typedef struct GtalkIqStanza__storage_ { + uint32_t _has_storage_[1]; + GtalkIqStanza_IqType type; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *from; + NSString *to; + GtalkErrorInfo *error; + GtalkExtension *extension; + NSString *persistentId; + int64_t rmqId; + int64_t accountId; + int64_t status; +} GtalkIqStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, rmqId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkIqStanza_IqType_EnumDescriptor, + .number = GtalkIqStanza_FieldNumber_Type, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldRequired | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_Id_p, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_From, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, from), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_To, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkIqStanza_FieldNumber_Error, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "extension", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkIqStanza_FieldNumber_Extension, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, extension), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_PersistentId, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_StreamId, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_AccountId, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_Status, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkIqStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkIqStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkIqStanza_IqType + +GPBEnumDescriptor *GtalkIqStanza_IqType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Get\000Set\000Result\000Error\000"; + static const int32_t values[] = { + GtalkIqStanza_IqType_Get, + GtalkIqStanza_IqType_Set, + GtalkIqStanza_IqType_Result, + GtalkIqStanza_IqType_Error, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkIqStanza_IqType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkIqStanza_IqType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkIqStanza_IqType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkIqStanza_IqType_Get: + case GtalkIqStanza_IqType_Set: + case GtalkIqStanza_IqType_Result: + case GtalkIqStanza_IqType_Error: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkAppData + +@implementation GtalkAppData + +@dynamic hasKey, key; +@dynamic hasValue, value; + +typedef struct GtalkAppData__storage_ { + uint32_t _has_storage_[1]; + NSString *key; + NSString *value; +} GtalkAppData__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "key", + .dataTypeSpecific.className = NULL, + .number = GtalkAppData_FieldNumber_Key, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkAppData__storage_, key), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GtalkAppData_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkAppData__storage_, value), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkAppData class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkAppData__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkDataMessageStanza + +@implementation GtalkDataMessageStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasCategory, category; +@dynamic hasToken, token; +@dynamic appDataArray, appDataArray_Count; +@dynamic hasFromTrustedServer, fromTrustedServer; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasPermission, permission; +@dynamic hasRegId, regId; +@dynamic hasPkgSignature, pkgSignature; +@dynamic hasClientId, clientId; +@dynamic hasDeviceUserId, deviceUserId; +@dynamic hasTtl, ttl; +@dynamic hasSent, sent; +@dynamic hasQueued, queued; +@dynamic hasStatus, status; +@dynamic hasRawData, rawData; +@dynamic hasMaxDelay, maxDelay; +@dynamic hasActualDelay, actualDelay; +@dynamic hasImmediateAck, immediateAck; +@dynamic hasDeliveryReceiptRequested, deliveryReceiptRequested; +@dynamic hasExternalMessageId, externalMessageId; +@dynamic hasFlags, flags; +@dynamic hasCellTower, cellTower; +@dynamic hasPriority, priority; + +typedef struct GtalkDataMessageStanza__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t ttl; + int32_t queued; + int32_t maxDelay; + int32_t actualDelay; + int32_t priority; + NSString *id_p; + NSString *from; + NSString *to; + NSString *category; + NSString *token; + NSMutableArray *appDataArray; + NSString *persistentId; + NSString *permission; + NSString *regId; + NSString *pkgSignature; + NSString *clientId; + NSData *rawData; + NSString *externalMessageId; + GtalkCellTower *cellTower; + int64_t rmqId; + int64_t deviceUserId; + int64_t sent; + int64_t status; + int64_t flags; +} GtalkDataMessageStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, rmqId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Id_p, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_From, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, from), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_To, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "category", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Category, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, category), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "token", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Token, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, token), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "appDataArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkAppData), + .number = GtalkDataMessageStanza_FieldNumber_AppDataArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, appDataArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "fromTrustedServer", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_FromTrustedServer, + .hasIndex = 6, + .offset = 7, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_PersistentId, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_StreamId, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "permission", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Permission, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, permission), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "regId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_RegId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, regId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "pkgSignature", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_PkgSignature, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, pkgSignature), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "clientId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ClientId, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, clientId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "deviceUserId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_DeviceUserId, + .hasIndex = 15, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, deviceUserId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "ttl", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Ttl, + .hasIndex = 16, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, ttl), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "sent", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Sent, + .hasIndex = 17, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, sent), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "queued", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Queued, + .hasIndex = 18, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, queued), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Status, + .hasIndex = 19, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "rawData", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_RawData, + .hasIndex = 20, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, rawData), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, + { + .name = "maxDelay", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_MaxDelay, + .hasIndex = 21, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, maxDelay), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "actualDelay", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ActualDelay, + .hasIndex = 22, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, actualDelay), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "immediateAck", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ImmediateAck, + .hasIndex = 23, + .offset = 24, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "deliveryReceiptRequested", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_DeliveryReceiptRequested, + .hasIndex = 25, + .offset = 26, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "externalMessageId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ExternalMessageId, + .hasIndex = 27, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, externalMessageId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "flags", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Flags, + .hasIndex = 28, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, flags), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkDataMessageStanza_FieldNumber_CellTower, + .hasIndex = 29, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "priority", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Priority, + .hasIndex = 30, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, priority), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkDataMessageStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkDataMessageStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkTalkMetadata + +@implementation GtalkTalkMetadata + +@dynamic hasForeground, foreground; + +typedef struct GtalkTalkMetadata__storage_ { + uint32_t _has_storage_[1]; +} GtalkTalkMetadata__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "foreground", + .dataTypeSpecific.className = NULL, + .number = GtalkTalkMetadata_FieldNumber_Foreground, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkTalkMetadata class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkTalkMetadata__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkCellTower + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" + +@implementation GtalkCellTower + +@dynamic hasId_p, id_p; +@dynamic hasKnownCongestionStatus, knownCongestionStatus; + +typedef struct GtalkCellTower__storage_ { + uint32_t _has_storage_[1]; + int32_t knownCongestionStatus; + NSString *id_p; +} GtalkCellTower__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkCellTower_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkCellTower__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "knownCongestionStatus", + .dataTypeSpecific.className = NULL, + .number = GtalkCellTower_FieldNumber_KnownCongestionStatus, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkCellTower__storage_, knownCongestionStatus), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkCellTower class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkCellTower__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma clang diagnostic pop + +#pragma mark - GtalkClientEvent + +@implementation GtalkClientEvent + +@dynamic hasType, type; +@dynamic hasNumberDiscardedEvents, numberDiscardedEvents; +@dynamic hasNetworkType, networkType; +@dynamic hasNetworkPort, networkPort; +@dynamic hasTimeConnectionStartedMs, timeConnectionStartedMs; +@dynamic hasTimeConnectionEndedMs, timeConnectionEndedMs; +@dynamic hasErrorCode, errorCode; +@dynamic hasTimeConnectionEstablishedMs, timeConnectionEstablishedMs; +@dynamic hasMcsReconnectAction, mcsReconnectAction; + +typedef struct GtalkClientEvent__storage_ { + uint32_t _has_storage_[1]; + GtalkClientEvent_Type type; + uint32_t numberDiscardedEvents; + int32_t networkType; + int32_t networkPort; + int32_t errorCode; + GtalkClientEvent_McsReconnectAction mcsReconnectAction; + uint64_t timeConnectionStartedMs; + uint64_t timeConnectionEndedMs; + uint64_t timeConnectionEstablishedMs; +} GtalkClientEvent__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkClientEvent_Type_EnumDescriptor, + .number = GtalkClientEvent_FieldNumber_Type, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "numberDiscardedEvents", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_NumberDiscardedEvents, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, numberDiscardedEvents), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt32, + }, + { + .name = "networkType", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_NetworkType, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, networkType), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "networkPort", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_NetworkPort, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, networkPort), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "timeConnectionStartedMs", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_TimeConnectionStartedMs, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, timeConnectionStartedMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "timeConnectionEndedMs", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_TimeConnectionEndedMs, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, timeConnectionEndedMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "errorCode", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_ErrorCode, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, errorCode), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "timeConnectionEstablishedMs", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_TimeConnectionEstablishedMs, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, timeConnectionEstablishedMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "mcsReconnectAction", + .dataTypeSpecific.enumDescFunc = GtalkClientEvent_McsReconnectAction_EnumDescriptor, + .number = GtalkClientEvent_FieldNumber_McsReconnectAction, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, mcsReconnectAction), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkClientEvent class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkClientEvent__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkClientEvent_Type + +GPBEnumDescriptor *GtalkClientEvent_Type_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Unknown\000DiscardedEvents\000FailedConnection" + "\000SuccessfulConnection\000McsReconnectReques" + "t\000FailedSocketCreationMcsReconnect\000McsRe" + "connectLimited\000"; + static const int32_t values[] = { + GtalkClientEvent_Type_Unknown, + GtalkClientEvent_Type_DiscardedEvents, + GtalkClientEvent_Type_FailedConnection, + GtalkClientEvent_Type_SuccessfulConnection, + GtalkClientEvent_Type_McsReconnectRequest, + GtalkClientEvent_Type_FailedSocketCreationMcsReconnect, + GtalkClientEvent_Type_McsReconnectLimited, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkClientEvent_Type) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkClientEvent_Type_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkClientEvent_Type_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkClientEvent_Type_Unknown: + case GtalkClientEvent_Type_DiscardedEvents: + case GtalkClientEvent_Type_FailedConnection: + case GtalkClientEvent_Type_SuccessfulConnection: + case GtalkClientEvent_Type_McsReconnectRequest: + case GtalkClientEvent_Type_FailedSocketCreationMcsReconnect: + case GtalkClientEvent_Type_McsReconnectLimited: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkClientEvent_McsReconnectAction + +GPBEnumDescriptor *GtalkClientEvent_McsReconnectAction_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "None\000NotConnected\000TooSoon\000"; + static const int32_t values[] = { + GtalkClientEvent_McsReconnectAction_None, + GtalkClientEvent_McsReconnectAction_NotConnected, + GtalkClientEvent_McsReconnectAction_TooSoon, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkClientEvent_McsReconnectAction) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkClientEvent_McsReconnectAction_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkClientEvent_McsReconnectAction_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkClientEvent_McsReconnectAction_None: + case GtalkClientEvent_McsReconnectAction_NotConnected: + case GtalkClientEvent_McsReconnectAction_TooSoon: + return YES; + default: + return NO; + } +} + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h new file mode 100644 index 0000000..f461884 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h @@ -0,0 +1,617 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_extensions.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GtalkOtrItem; +@class GtalkPhoto; +@class GtalkRosterItem; +@class GtalkSharedStatus_StatusList; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GtalkRosterItem_SubscriptionType + +typedef GPB_ENUM(GtalkRosterItem_SubscriptionType) { + GtalkRosterItem_SubscriptionType_None = 0, + GtalkRosterItem_SubscriptionType_To = 1, + GtalkRosterItem_SubscriptionType_From = 2, + GtalkRosterItem_SubscriptionType_Both = 3, + GtalkRosterItem_SubscriptionType_Remove = 4, +}; + +GPBEnumDescriptor *GtalkRosterItem_SubscriptionType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkRosterItem_SubscriptionType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkRosterItem_AskType + +typedef GPB_ENUM(GtalkRosterItem_AskType) { + GtalkRosterItem_AskType_Subscribe = 0, +}; + +GPBEnumDescriptor *GtalkRosterItem_AskType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkRosterItem_AskType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkRosterItem_DisplayType + +typedef GPB_ENUM(GtalkRosterItem_DisplayType) { + GtalkRosterItem_DisplayType_Blocked = 0, + GtalkRosterItem_DisplayType_Hidden = 1, + GtalkRosterItem_DisplayType_Pinned = 2, +}; + +GPBEnumDescriptor *GtalkRosterItem_DisplayType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkRosterItem_DisplayType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkSharedStatus_ShowType + +typedef GPB_ENUM(GtalkSharedStatus_ShowType) { + GtalkSharedStatus_ShowType_Default = 0, + GtalkSharedStatus_ShowType_Dnd = 1, +}; + +GPBEnumDescriptor *GtalkSharedStatus_ShowType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkSharedStatus_ShowType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPostAuthBatchQuery_CapabilitiesExtFlags + +typedef GPB_ENUM(GtalkPostAuthBatchQuery_CapabilitiesExtFlags) { + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVoiceV1 = 1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVideoV1 = 2, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasCameraV1 = 4, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasPmucV1 = 8, +}; + +GPBEnumDescriptor *GtalkPostAuthBatchQuery_CapabilitiesExtFlags_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPostAuthBatchQuery_CapabilitiesExtFlags_IsValidValue(int32_t value); + +#pragma mark - GtalkGtalkExtensionsRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GtalkGtalkExtensionsRoot : GPBRootObject +@end + +#pragma mark - GtalkRosterQuery + +typedef GPB_ENUM(GtalkRosterQuery_FieldNumber) { + GtalkRosterQuery_FieldNumber_Etag = 1, + GtalkRosterQuery_FieldNumber_NotModified = 2, + GtalkRosterQuery_FieldNumber_ItemArray = 3, + GtalkRosterQuery_FieldNumber_AvatarWidth = 4, + GtalkRosterQuery_FieldNumber_AvatarHeight = 5, +}; + +@interface GtalkRosterQuery : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *etag; +/** Test to see if @c etag has been set. */ +@property(nonatomic, readwrite) BOOL hasEtag; + + +@property(nonatomic, readwrite) BOOL notModified; + +@property(nonatomic, readwrite) BOOL hasNotModified; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *itemArray; +/** The number of items in @c itemArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger itemArray_Count; + + +@property(nonatomic, readwrite) int32_t avatarWidth; + +@property(nonatomic, readwrite) BOOL hasAvatarWidth; + +@property(nonatomic, readwrite) int32_t avatarHeight; + +@property(nonatomic, readwrite) BOOL hasAvatarHeight; +@end + +#pragma mark - GtalkRosterItem + +typedef GPB_ENUM(GtalkRosterItem_FieldNumber) { + GtalkRosterItem_FieldNumber_Jid = 1, + GtalkRosterItem_FieldNumber_Name = 2, + GtalkRosterItem_FieldNumber_Subscription = 3, + GtalkRosterItem_FieldNumber_Ask = 4, + GtalkRosterItem_FieldNumber_GroupArray = 5, + GtalkRosterItem_FieldNumber_QuickContact = 6, + GtalkRosterItem_FieldNumber_Display = 7, + GtalkRosterItem_FieldNumber_Rejected = 8, +}; + +@interface GtalkRosterItem : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; +/** Test to see if @c name has been set. */ +@property(nonatomic, readwrite) BOOL hasName; + + +@property(nonatomic, readwrite) GtalkRosterItem_SubscriptionType subscription; + +@property(nonatomic, readwrite) BOOL hasSubscription; + +@property(nonatomic, readwrite) GtalkRosterItem_AskType ask; + +@property(nonatomic, readwrite) BOOL hasAsk; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *groupArray; +/** The number of items in @c groupArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger groupArray_Count; + + +@property(nonatomic, readwrite) BOOL quickContact; + +@property(nonatomic, readwrite) BOOL hasQuickContact; + +@property(nonatomic, readwrite) GtalkRosterItem_DisplayType display; + +@property(nonatomic, readwrite) BOOL hasDisplay; + +@property(nonatomic, readwrite) BOOL rejected; + +@property(nonatomic, readwrite) BOOL hasRejected; +@end + +#pragma mark - GtalkRmqLastId + +typedef GPB_ENUM(GtalkRmqLastId_FieldNumber) { + GtalkRmqLastId_FieldNumber_Id_p = 1, +}; + +@interface GtalkRmqLastId : GPBMessage + + +@property(nonatomic, readwrite) int64_t id_p; + +@property(nonatomic, readwrite) BOOL hasId_p; +@end + +#pragma mark - GtalkRmqAck + +typedef GPB_ENUM(GtalkRmqAck_FieldNumber) { + GtalkRmqAck_FieldNumber_Id_p = 1, +}; + +@interface GtalkRmqAck : GPBMessage + + +@property(nonatomic, readwrite) int64_t id_p; + +@property(nonatomic, readwrite) BOOL hasId_p; +@end + +#pragma mark - GtalkVCard + +typedef GPB_ENUM(GtalkVCard_FieldNumber) { + GtalkVCard_FieldNumber_Version = 1, + GtalkVCard_FieldNumber_FullName = 2, + GtalkVCard_FieldNumber_Photo = 3, + GtalkVCard_FieldNumber_AvatarHash = 4, + GtalkVCard_FieldNumber_Modified = 5, +}; + +@interface GtalkVCard : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *version; +/** Test to see if @c version has been set. */ +@property(nonatomic, readwrite) BOOL hasVersion; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *fullName; +/** Test to see if @c fullName has been set. */ +@property(nonatomic, readwrite) BOOL hasFullName; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkPhoto *photo; +/** Test to see if @c photo has been set. */ +@property(nonatomic, readwrite) BOOL hasPhoto; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *avatarHash; +/** Test to see if @c avatarHash has been set. */ +@property(nonatomic, readwrite) BOOL hasAvatarHash; + + +@property(nonatomic, readwrite) BOOL modified; + +@property(nonatomic, readwrite) BOOL hasModified; +@end + +#pragma mark - GtalkPhoto + +typedef GPB_ENUM(GtalkPhoto_FieldNumber) { + GtalkPhoto_FieldNumber_Type = 1, + GtalkPhoto_FieldNumber_Data_p = 2, +}; + +@interface GtalkPhoto : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *type; +/** Test to see if @c type has been set. */ +@property(nonatomic, readwrite) BOOL hasType; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *data_p; +/** Test to see if @c data_p has been set. */ +@property(nonatomic, readwrite) BOOL hasData_p; + +@end + +#pragma mark - GtalkChatRead + +typedef GPB_ENUM(GtalkChatRead_FieldNumber) { + GtalkChatRead_FieldNumber_User = 1, +}; + +@interface GtalkChatRead : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + +@end + +#pragma mark - GtalkChatClosed + +typedef GPB_ENUM(GtalkChatClosed_FieldNumber) { + GtalkChatClosed_FieldNumber_User = 1, +}; + +@interface GtalkChatClosed : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + +@end + +#pragma mark - GtalkCapabilities + +typedef GPB_ENUM(GtalkCapabilities_FieldNumber) { + GtalkCapabilities_FieldNumber_Node = 1, + GtalkCapabilities_FieldNumber_Ver = 2, + GtalkCapabilities_FieldNumber_Ext = 3, + GtalkCapabilities_FieldNumber_Hash_p = 4, +}; + +@interface GtalkCapabilities : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *node; +/** Test to see if @c node has been set. */ +@property(nonatomic, readwrite) BOOL hasNode; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ver; +/** Test to see if @c ver has been set. */ +@property(nonatomic, readwrite) BOOL hasVer; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ext; +/** Test to see if @c ext has been set. */ +@property(nonatomic, readwrite) BOOL hasExt; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *hash_p; +/** Test to see if @c hash_p has been set. */ +@property(nonatomic, readwrite) BOOL hasHash_p; + +@end + +#pragma mark - GtalkSharedStatus + +typedef GPB_ENUM(GtalkSharedStatus_FieldNumber) { + GtalkSharedStatus_FieldNumber_StatusMax = 1, + GtalkSharedStatus_FieldNumber_StatusListMax = 2, + GtalkSharedStatus_FieldNumber_StatusListContentsMax = 3, + GtalkSharedStatus_FieldNumber_Status = 4, + GtalkSharedStatus_FieldNumber_Show = 5, + GtalkSharedStatus_FieldNumber_StatusListArray = 6, + GtalkSharedStatus_FieldNumber_Invisible = 9, + GtalkSharedStatus_FieldNumber_StatusMinVersion = 10, +}; + +@interface GtalkSharedStatus : GPBMessage + + +@property(nonatomic, readwrite) int32_t statusMax; + +@property(nonatomic, readwrite) BOOL hasStatusMax; + +@property(nonatomic, readwrite) int32_t statusListMax; + +@property(nonatomic, readwrite) BOOL hasStatusListMax; + +@property(nonatomic, readwrite) int32_t statusListContentsMax; + +@property(nonatomic, readwrite) BOOL hasStatusListContentsMax; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *status; +/** Test to see if @c status has been set. */ +@property(nonatomic, readwrite) BOOL hasStatus; + + +@property(nonatomic, readwrite) GtalkSharedStatus_ShowType show; + +@property(nonatomic, readwrite) BOOL hasShow; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *statusListArray; +/** The number of items in @c statusListArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger statusListArray_Count; + + +@property(nonatomic, readwrite) BOOL invisible; + +@property(nonatomic, readwrite) BOOL hasInvisible; + +@property(nonatomic, readwrite) int32_t statusMinVersion; + +@property(nonatomic, readwrite) BOOL hasStatusMinVersion; +@end + +#pragma mark - GtalkSharedStatus_StatusList + +typedef GPB_ENUM(GtalkSharedStatus_StatusList_FieldNumber) { + GtalkSharedStatus_StatusList_FieldNumber_Show = 7, + GtalkSharedStatus_StatusList_FieldNumber_StatusArray = 8, +}; + +@interface GtalkSharedStatus_StatusList : GPBMessage + + +@property(nonatomic, readwrite) GtalkSharedStatus_ShowType show; + +@property(nonatomic, readwrite) BOOL hasShow; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *statusArray; +/** The number of items in @c statusArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger statusArray_Count; + +@end + +#pragma mark - GtalkOtrQuery + +typedef GPB_ENUM(GtalkOtrQuery_FieldNumber) { + GtalkOtrQuery_FieldNumber_NosaveDefault = 1, + GtalkOtrQuery_FieldNumber_ItemArray = 2, + GtalkOtrQuery_FieldNumber_Etag = 3, + GtalkOtrQuery_FieldNumber_NotModified = 4, +}; + +@interface GtalkOtrQuery : GPBMessage + + +@property(nonatomic, readwrite) BOOL nosaveDefault; + +@property(nonatomic, readwrite) BOOL hasNosaveDefault; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *itemArray; +/** The number of items in @c itemArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger itemArray_Count; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *etag; +/** Test to see if @c etag has been set. */ +@property(nonatomic, readwrite) BOOL hasEtag; + + +@property(nonatomic, readwrite) BOOL notModified; + +@property(nonatomic, readwrite) BOOL hasNotModified; +@end + +#pragma mark - GtalkOtrItem + +typedef GPB_ENUM(GtalkOtrItem_FieldNumber) { + GtalkOtrItem_FieldNumber_Jid = 1, + GtalkOtrItem_FieldNumber_Nosave = 2, + GtalkOtrItem_FieldNumber_ChangedByBuddy = 3, +}; + +@interface GtalkOtrItem : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite) BOOL nosave; + +@property(nonatomic, readwrite) BOOL hasNosave; + +@property(nonatomic, readwrite) BOOL changedByBuddy; + +@property(nonatomic, readwrite) BOOL hasChangedByBuddy; +@end + +#pragma mark - GtalkIdle + +typedef GPB_ENUM(GtalkIdle_FieldNumber) { + GtalkIdle_FieldNumber_Idle = 1, + GtalkIdle_FieldNumber_Away = 2, +}; + +@interface GtalkIdle : GPBMessage + + +@property(nonatomic, readwrite) BOOL idle; + +@property(nonatomic, readwrite) BOOL hasIdle; + +@property(nonatomic, readwrite) BOOL away; + +@property(nonatomic, readwrite) BOOL hasAway; +@end + +#pragma mark - GtalkPostAuthBatchQuery + +typedef GPB_ENUM(GtalkPostAuthBatchQuery_FieldNumber) { + GtalkPostAuthBatchQuery_FieldNumber_Available = 1, + GtalkPostAuthBatchQuery_FieldNumber_DeviceIdle = 2, + GtalkPostAuthBatchQuery_FieldNumber_MobileIndicator = 3, + GtalkPostAuthBatchQuery_FieldNumber_SharedStatusVersion = 4, + GtalkPostAuthBatchQuery_FieldNumber_RosterEtag = 5, + GtalkPostAuthBatchQuery_FieldNumber_OtrEtag = 6, + GtalkPostAuthBatchQuery_FieldNumber_AvatarHash = 7, + GtalkPostAuthBatchQuery_FieldNumber_VcardQueryStanzaId = 8, + GtalkPostAuthBatchQuery_FieldNumber_CapabilitiesExtFlags = 9, +}; + +@interface GtalkPostAuthBatchQuery : GPBMessage + + +@property(nonatomic, readwrite) BOOL available; + +@property(nonatomic, readwrite) BOOL hasAvailable; + +@property(nonatomic, readwrite) BOOL deviceIdle; + +@property(nonatomic, readwrite) BOOL hasDeviceIdle; + +@property(nonatomic, readwrite) BOOL mobileIndicator; + +@property(nonatomic, readwrite) BOOL hasMobileIndicator; + +@property(nonatomic, readwrite) int32_t sharedStatusVersion; + +@property(nonatomic, readwrite) BOOL hasSharedStatusVersion; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *rosterEtag; +/** Test to see if @c rosterEtag has been set. */ +@property(nonatomic, readwrite) BOOL hasRosterEtag; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *otrEtag; +/** Test to see if @c otrEtag has been set. */ +@property(nonatomic, readwrite) BOOL hasOtrEtag; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *avatarHash; +/** Test to see if @c avatarHash has been set. */ +@property(nonatomic, readwrite) BOOL hasAvatarHash; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *vcardQueryStanzaId; +/** Test to see if @c vcardQueryStanzaId has been set. */ +@property(nonatomic, readwrite) BOOL hasVcardQueryStanzaId; + + +@property(nonatomic, readwrite) int32_t capabilitiesExtFlags; + +@property(nonatomic, readwrite) BOOL hasCapabilitiesExtFlags; +@end + +#pragma mark - GtalkStreamAck + +@interface GtalkStreamAck : GPBMessage + +@end + +#pragma mark - GtalkSelectiveAck + +typedef GPB_ENUM(GtalkSelectiveAck_FieldNumber) { + GtalkSelectiveAck_FieldNumber_IdArray = 1, +}; + +@interface GtalkSelectiveAck : GPBMessage + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *idArray; +/** The number of items in @c idArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger idArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m new file mode 100644 index 0000000..e41d416 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m @@ -0,0 +1,1407 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_extensions.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + + #import "GtalkExtensions.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GtalkGtalkExtensionsRoot + +@implementation GtalkGtalkExtensionsRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GtalkGtalkExtensionsRoot_FileDescriptor + +static GPBFileDescriptor *GtalkGtalkExtensionsRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"mobilegtalk" + objcPrefix:@"Gtalk" + syntax:GPBFileSyntaxProto2]; + } + return descriptor; +} + +#pragma mark - GtalkRosterQuery + +@implementation GtalkRosterQuery + +@dynamic hasEtag, etag; +@dynamic hasNotModified, notModified; +@dynamic itemArray, itemArray_Count; +@dynamic hasAvatarWidth, avatarWidth; +@dynamic hasAvatarHeight, avatarHeight; + +typedef struct GtalkRosterQuery__storage_ { + uint32_t _has_storage_[1]; + int32_t avatarWidth; + int32_t avatarHeight; + NSString *etag; + NSMutableArray *itemArray; +} GtalkRosterQuery__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "etag", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_Etag, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, etag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "notModified", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_NotModified, + .hasIndex = 1, + .offset = 2, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "itemArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkRosterItem), + .number = GtalkRosterQuery_FieldNumber_ItemArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, itemArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "avatarWidth", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_AvatarWidth, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, avatarWidth), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt32, + }, + { + .name = "avatarHeight", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_AvatarHeight, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, avatarHeight), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRosterQuery class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRosterQuery__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\002\004\013\000\005\014\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkRosterItem + +@implementation GtalkRosterItem + +@dynamic hasJid, jid; +@dynamic hasName, name; +@dynamic hasSubscription, subscription; +@dynamic hasAsk, ask; +@dynamic groupArray, groupArray_Count; +@dynamic hasQuickContact, quickContact; +@dynamic hasDisplay, display; +@dynamic hasRejected, rejected; + +typedef struct GtalkRosterItem__storage_ { + uint32_t _has_storage_[1]; + GtalkRosterItem_SubscriptionType subscription; + GtalkRosterItem_AskType ask; + GtalkRosterItem_DisplayType display; + NSString *jid; + NSString *name; + NSMutableArray *groupArray; +} GtalkRosterItem__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_Jid, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, jid), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_Name, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "subscription", + .dataTypeSpecific.enumDescFunc = GtalkRosterItem_SubscriptionType_EnumDescriptor, + .number = GtalkRosterItem_FieldNumber_Subscription, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, subscription), + .flags = (GPBFieldFlags)(GPBFieldRequired | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "ask", + .dataTypeSpecific.enumDescFunc = GtalkRosterItem_AskType_EnumDescriptor, + .number = GtalkRosterItem_FieldNumber_Ask, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, ask), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "groupArray", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_GroupArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, groupArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "quickContact", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_QuickContact, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "display", + .dataTypeSpecific.enumDescFunc = GtalkRosterItem_DisplayType_EnumDescriptor, + .number = GtalkRosterItem_FieldNumber_Display, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, display), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "rejected", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_Rejected, + .hasIndex = 7, + .offset = 8, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRosterItem class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRosterItem__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkRosterItem_SubscriptionType + +GPBEnumDescriptor *GtalkRosterItem_SubscriptionType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "None\000To\000From\000Both\000Remove\000"; + static const int32_t values[] = { + GtalkRosterItem_SubscriptionType_None, + GtalkRosterItem_SubscriptionType_To, + GtalkRosterItem_SubscriptionType_From, + GtalkRosterItem_SubscriptionType_Both, + GtalkRosterItem_SubscriptionType_Remove, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkRosterItem_SubscriptionType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkRosterItem_SubscriptionType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkRosterItem_SubscriptionType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkRosterItem_SubscriptionType_None: + case GtalkRosterItem_SubscriptionType_To: + case GtalkRosterItem_SubscriptionType_From: + case GtalkRosterItem_SubscriptionType_Both: + case GtalkRosterItem_SubscriptionType_Remove: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkRosterItem_AskType + +GPBEnumDescriptor *GtalkRosterItem_AskType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Subscribe\000"; + static const int32_t values[] = { + GtalkRosterItem_AskType_Subscribe, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkRosterItem_AskType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkRosterItem_AskType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkRosterItem_AskType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkRosterItem_AskType_Subscribe: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkRosterItem_DisplayType + +GPBEnumDescriptor *GtalkRosterItem_DisplayType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Blocked\000Hidden\000Pinned\000"; + static const int32_t values[] = { + GtalkRosterItem_DisplayType_Blocked, + GtalkRosterItem_DisplayType_Hidden, + GtalkRosterItem_DisplayType_Pinned, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkRosterItem_DisplayType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkRosterItem_DisplayType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkRosterItem_DisplayType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkRosterItem_DisplayType_Blocked: + case GtalkRosterItem_DisplayType_Hidden: + case GtalkRosterItem_DisplayType_Pinned: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkRmqLastId + +@implementation GtalkRmqLastId + +@dynamic hasId_p, id_p; + +typedef struct GtalkRmqLastId__storage_ { + uint32_t _has_storage_[1]; + int64_t id_p; +} GtalkRmqLastId__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkRmqLastId_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRmqLastId__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRmqLastId class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRmqLastId__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkRmqAck + +@implementation GtalkRmqAck + +@dynamic hasId_p, id_p; + +typedef struct GtalkRmqAck__storage_ { + uint32_t _has_storage_[1]; + int64_t id_p; +} GtalkRmqAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkRmqAck_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRmqAck__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRmqAck class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRmqAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkVCard + +@implementation GtalkVCard + +@dynamic hasVersion, version; +@dynamic hasFullName, fullName; +@dynamic hasPhoto, photo; +@dynamic hasAvatarHash, avatarHash; +@dynamic hasModified, modified; + +typedef struct GtalkVCard__storage_ { + uint32_t _has_storage_[1]; + NSString *version; + NSString *fullName; + GtalkPhoto *photo; + NSString *avatarHash; +} GtalkVCard__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "version", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_Version, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, version), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "fullName", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_FullName, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, fullName), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "photo", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkPhoto), + .number = GtalkVCard_FieldNumber_Photo, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, photo), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "avatarHash", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_AvatarHash, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, avatarHash), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "modified", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_Modified, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkVCard class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkVCard__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkPhoto + +@implementation GtalkPhoto + +@dynamic hasType, type; +@dynamic hasData_p, data_p; + +typedef struct GtalkPhoto__storage_ { + uint32_t _has_storage_[1]; + NSString *type; + NSString *data_p; +} GtalkPhoto__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "type", + .dataTypeSpecific.className = NULL, + .number = GtalkPhoto_FieldNumber_Type, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkPhoto__storage_, type), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "data_p", + .dataTypeSpecific.className = NULL, + .number = GtalkPhoto_FieldNumber_Data_p, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkPhoto__storage_, data_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkPhoto class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkPhoto__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkChatRead + +@implementation GtalkChatRead + +@dynamic hasUser, user; + +typedef struct GtalkChatRead__storage_ { + uint32_t _has_storage_[1]; + NSString *user; +} GtalkChatRead__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkChatRead_FieldNumber_User, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkChatRead__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkChatRead class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkChatRead__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkChatClosed + +@implementation GtalkChatClosed + +@dynamic hasUser, user; + +typedef struct GtalkChatClosed__storage_ { + uint32_t _has_storage_[1]; + NSString *user; +} GtalkChatClosed__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkChatClosed_FieldNumber_User, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkChatClosed__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkChatClosed class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkChatClosed__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkCapabilities + +@implementation GtalkCapabilities + +@dynamic hasNode, node; +@dynamic hasVer, ver; +@dynamic hasExt, ext; +@dynamic hasHash_p, hash_p; + +typedef struct GtalkCapabilities__storage_ { + uint32_t _has_storage_[1]; + NSString *node; + NSString *ver; + NSString *ext; + NSString *hash_p; +} GtalkCapabilities__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "node", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Node, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, node), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "ver", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Ver, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, ver), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "ext", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Ext, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, ext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "hash_p", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Hash_p, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, hash_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkCapabilities class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkCapabilities__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkSharedStatus + +@implementation GtalkSharedStatus + +@dynamic hasStatusMax, statusMax; +@dynamic hasStatusListMax, statusListMax; +@dynamic hasStatusListContentsMax, statusListContentsMax; +@dynamic hasStatus, status; +@dynamic hasShow, show; +@dynamic statusListArray, statusListArray_Count; +@dynamic hasInvisible, invisible; +@dynamic hasStatusMinVersion, statusMinVersion; + +typedef struct GtalkSharedStatus__storage_ { + uint32_t _has_storage_[1]; + int32_t statusMax; + int32_t statusListMax; + int32_t statusListContentsMax; + GtalkSharedStatus_ShowType show; + int32_t statusMinVersion; + NSString *status; + NSMutableArray *statusListArray; +} GtalkSharedStatus__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "statusMax", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusMax, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusMax), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "statusListMax", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusListMax, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusListMax), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "statusListContentsMax", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusListContentsMax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusListContentsMax), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_Status, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "show", + .dataTypeSpecific.enumDescFunc = GtalkSharedStatus_ShowType_EnumDescriptor, + .number = GtalkSharedStatus_FieldNumber_Show, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, show), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "statusListArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkSharedStatus_StatusList), + .number = GtalkSharedStatus_FieldNumber_StatusListArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusListArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeGroup, + }, + { + .name = "invisible", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_Invisible, + .hasIndex = 5, + .offset = 6, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "statusMinVersion", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusMinVersion, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusMinVersion), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSharedStatus class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSharedStatus__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkSharedStatus_ShowType + +GPBEnumDescriptor *GtalkSharedStatus_ShowType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Default\000Dnd\000"; + static const int32_t values[] = { + GtalkSharedStatus_ShowType_Default, + GtalkSharedStatus_ShowType_Dnd, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkSharedStatus_ShowType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkSharedStatus_ShowType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkSharedStatus_ShowType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkSharedStatus_ShowType_Default: + case GtalkSharedStatus_ShowType_Dnd: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkSharedStatus_StatusList + +@implementation GtalkSharedStatus_StatusList + +@dynamic hasShow, show; +@dynamic statusArray, statusArray_Count; + +typedef struct GtalkSharedStatus_StatusList__storage_ { + uint32_t _has_storage_[1]; + GtalkSharedStatus_ShowType show; + NSMutableArray *statusArray; +} GtalkSharedStatus_StatusList__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "show", + .dataTypeSpecific.enumDescFunc = GtalkSharedStatus_ShowType_EnumDescriptor, + .number = GtalkSharedStatus_StatusList_FieldNumber_Show, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkSharedStatus_StatusList__storage_, show), + .flags = (GPBFieldFlags)(GPBFieldRequired | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "statusArray", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_StatusList_FieldNumber_StatusArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkSharedStatus_StatusList__storage_, statusArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSharedStatus_StatusList class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSharedStatus_StatusList__storage_) + flags:GPBDescriptorInitializationFlag_None]; + [localDescriptor setupContainingMessageClassName:GPBStringifySymbol(GtalkSharedStatus)]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkOtrQuery + +@implementation GtalkOtrQuery + +@dynamic hasNosaveDefault, nosaveDefault; +@dynamic itemArray, itemArray_Count; +@dynamic hasEtag, etag; +@dynamic hasNotModified, notModified; + +typedef struct GtalkOtrQuery__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *itemArray; + NSString *etag; +} GtalkOtrQuery__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "nosaveDefault", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrQuery_FieldNumber_NosaveDefault, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "itemArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkOtrItem), + .number = GtalkOtrQuery_FieldNumber_ItemArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkOtrQuery__storage_, itemArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "etag", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrQuery_FieldNumber_Etag, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkOtrQuery__storage_, etag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "notModified", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrQuery_FieldNumber_NotModified, + .hasIndex = 3, + .offset = 4, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkOtrQuery class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkOtrQuery__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkOtrItem + +@implementation GtalkOtrItem + +@dynamic hasJid, jid; +@dynamic hasNosave, nosave; +@dynamic hasChangedByBuddy, changedByBuddy; + +typedef struct GtalkOtrItem__storage_ { + uint32_t _has_storage_[1]; + NSString *jid; +} GtalkOtrItem__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrItem_FieldNumber_Jid, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkOtrItem__storage_, jid), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "nosave", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrItem_FieldNumber_Nosave, + .hasIndex = 1, + .offset = 2, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "changedByBuddy", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrItem_FieldNumber_ChangedByBuddy, + .hasIndex = 3, + .offset = 4, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkOtrItem class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkOtrItem__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkIdle + +@implementation GtalkIdle + +@dynamic hasIdle, idle; +@dynamic hasAway, away; + +typedef struct GtalkIdle__storage_ { + uint32_t _has_storage_[1]; +} GtalkIdle__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "idle", + .dataTypeSpecific.className = NULL, + .number = GtalkIdle_FieldNumber_Idle, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "away", + .dataTypeSpecific.className = NULL, + .number = GtalkIdle_FieldNumber_Away, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkIdle class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkIdle__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkPostAuthBatchQuery + +@implementation GtalkPostAuthBatchQuery + +@dynamic hasAvailable, available; +@dynamic hasDeviceIdle, deviceIdle; +@dynamic hasMobileIndicator, mobileIndicator; +@dynamic hasSharedStatusVersion, sharedStatusVersion; +@dynamic hasRosterEtag, rosterEtag; +@dynamic hasOtrEtag, otrEtag; +@dynamic hasAvatarHash, avatarHash; +@dynamic hasVcardQueryStanzaId, vcardQueryStanzaId; +@dynamic hasCapabilitiesExtFlags, capabilitiesExtFlags; + +typedef struct GtalkPostAuthBatchQuery__storage_ { + uint32_t _has_storage_[1]; + int32_t sharedStatusVersion; + int32_t capabilitiesExtFlags; + NSString *rosterEtag; + NSString *otrEtag; + NSString *avatarHash; + NSString *vcardQueryStanzaId; +} GtalkPostAuthBatchQuery__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "available", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_Available, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "deviceIdle", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_DeviceIdle, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "mobileIndicator", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_MobileIndicator, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "sharedStatusVersion", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_SharedStatusVersion, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, sharedStatusVersion), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "rosterEtag", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_RosterEtag, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, rosterEtag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "otrEtag", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_OtrEtag, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, otrEtag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "avatarHash", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_AvatarHash, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, avatarHash), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "vcardQueryStanzaId", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_VcardQueryStanzaId, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, vcardQueryStanzaId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "capabilitiesExtFlags", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_CapabilitiesExtFlags, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, capabilitiesExtFlags), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkPostAuthBatchQuery class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkPostAuthBatchQuery__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkPostAuthBatchQuery_CapabilitiesExtFlags + +GPBEnumDescriptor *GtalkPostAuthBatchQuery_CapabilitiesExtFlags_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "HasVoiceV1\000HasVideoV1\000HasCameraV1\000HasPmu" + "cV1\000"; + static const int32_t values[] = { + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVoiceV1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVideoV1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasCameraV1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasPmucV1, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPostAuthBatchQuery_CapabilitiesExtFlags) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPostAuthBatchQuery_CapabilitiesExtFlags_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPostAuthBatchQuery_CapabilitiesExtFlags_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVoiceV1: + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVideoV1: + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasCameraV1: + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasPmucV1: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkStreamAck + +@implementation GtalkStreamAck + + +typedef struct GtalkStreamAck__storage_ { + uint32_t _has_storage_[1]; +} GtalkStreamAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkStreamAck class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GtalkStreamAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkSelectiveAck + +@implementation GtalkSelectiveAck + +@dynamic idArray, idArray_Count; + +typedef struct GtalkSelectiveAck__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *idArray; +} GtalkSelectiveAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "idArray", + .dataTypeSpecific.className = NULL, + .number = GtalkSelectiveAck_FieldNumber_IdArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkSelectiveAck__storage_, idArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSelectiveAck class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSelectiveAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessaging.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessaging.h new file mode 100644 index 0000000..15caf8e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessaging.h @@ -0,0 +1,497 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * @related FIRMessaging + * + * The completion handler invoked when the registration token returns. + * If the call fails we return the appropriate `error code`, described by + * `FIRMessagingError`. + * + * @param FCMToken The valid registration token returned by FCM. + * @param error The error describing why a token request failed. The error code + * will match a value from the FIRMessagingError enumeration. + */ +typedef void(^FIRMessagingFCMTokenFetchCompletion)(NSString * _Nullable FCMToken, + NSError * _Nullable error) + NS_SWIFT_NAME(MessagingFCMTokenFetchCompletion); + + +/** + * @related FIRMessaging + * + * The completion handler invoked when the registration token deletion request is + * completed. If the call fails we return the appropriate `error code`, described + * by `FIRMessagingError`. + * + * @param error The error describing why a token deletion failed. The error code + * will match a value from the FIRMessagingError enumeration. + */ +typedef void(^FIRMessagingDeleteFCMTokenCompletion)(NSError * _Nullable error) + NS_SWIFT_NAME(MessagingDeleteFCMTokenCompletion); + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param error The error which occurred while updating the subscription topic + * on the FIRMessaging server. This will be nil in case the operation + * was successful, or if the operation was cancelled. + */ +typedef void (^FIRMessagingTopicOperationCompletion)(NSError *_Nullable error); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Notification sent when the upstream message has been delivered + * successfully to the server. The notification object will be the messageID + * of the successfully delivered message. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingSendSuccessNotification + NS_SWIFT_NAME(MessagingSendSuccess); + +/** + * Notification sent when the upstream message was failed to be sent to the + * server. The notification object will be the messageID of the failed + * message. The userInfo dictionary will contain the relevant error + * information for the failure. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingSendErrorNotification + NS_SWIFT_NAME(MessagingSendError); + +/** + * Notification sent when the Firebase messaging server deletes pending + * messages due to exceeded storage limits. This may occur, for example, when + * the device cannot be reached for an extended period of time. + * + * It is recommended to retrieve any missing messages directly from the + * server. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingMessagesDeletedNotification + NS_SWIFT_NAME(MessagingMessagesDeleted); + +/** + * Notification sent when Firebase Messaging establishes or disconnects from + * an FCM socket connection. You can query the connection state in this + * notification by checking the `isDirectChannelEstablished` property of FIRMessaging. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingConnectionStateChangedNotification + NS_SWIFT_NAME(MessagingConnectionStateChanged); + +/** + * Notification sent when the FCM registration token has been refreshed. Please use the + * FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and + * updated tokens. + */ +FOUNDATION_EXPORT const NSNotificationName + FIRMessagingRegistrationTokenRefreshedNotification + NS_SWIFT_NAME(MessagingRegistrationTokenRefreshed); +#else +/** + * Notification sent when the upstream message has been delivered + * successfully to the server. The notification object will be the messageID + * of the successfully delivered message. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingSendSuccessNotification + NS_SWIFT_NAME(MessagingSendSuccessNotification); + +/** + * Notification sent when the upstream message was failed to be sent to the + * server. The notification object will be the messageID of the failed + * message. The userInfo dictionary will contain the relevant error + * information for the failure. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingSendErrorNotification + NS_SWIFT_NAME(MessagingSendErrorNotification); + +/** + * Notification sent when the Firebase messaging server deletes pending + * messages due to exceeded storage limits. This may occur, for example, when + * the device cannot be reached for an extended period of time. + * + * It is recommended to retrieve any missing messages directly from the + * server. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingMessagesDeletedNotification + NS_SWIFT_NAME(MessagingMessagesDeletedNotification); + +/** + * Notification sent when Firebase Messaging establishes or disconnects from + * an FCM socket connection. You can query the connection state in this + * notification by checking the `isDirectChannelEstablished` property of FIRMessaging. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingConnectionStateChangedNotification + NS_SWIFT_NAME(MessagingConnectionStateChangedNotification); + +/** + * Notification sent when the FCM registration token has been refreshed. Please use the + * FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and + * updated tokens. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingRegistrationTokenRefreshedNotification + NS_SWIFT_NAME(MessagingRegistrationTokenRefreshedNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @enum FIRMessagingError + */ +typedef NS_ENUM(NSUInteger, FIRMessagingError) { + /// Unknown error. + FIRMessagingErrorUnknown = 0, + + /// FIRMessaging couldn't validate request from this client. + FIRMessagingErrorAuthentication = 1, + + /// InstanceID service cannot be accessed. + FIRMessagingErrorNoAccess = 2, + + /// Request to InstanceID backend timed out. + FIRMessagingErrorTimeout = 3, + + /// No network available to reach the servers. + FIRMessagingErrorNetwork = 4, + + /// Another similar operation in progress, bailing this one. + FIRMessagingErrorOperationInProgress = 5, + + /// Some parameters of the request were invalid. + FIRMessagingErrorInvalidRequest = 7, + + /// Topic name is invalid for subscription/unsubscription. + FIRMessagingErrorInvalidTopicName = 8, + +} NS_SWIFT_NAME(MessagingError); + +/// Status for the downstream message received by the app. +typedef NS_ENUM(NSInteger, FIRMessagingMessageStatus) { + /// Unknown status. + FIRMessagingMessageStatusUnknown, + /// New downstream message received by the app. + FIRMessagingMessageStatusNew, +} NS_SWIFT_NAME(MessagingMessageStatus); + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * Firebase Messaging will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * Unless you really need to specify the type, you should use the `APNSToken` + * property instead. + */ +typedef NS_ENUM(NSInteger, FIRMessagingAPNSTokenType) { + /// Unknown token type. + FIRMessagingAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRMessagingAPNSTokenTypeSandbox, + /// Production token type. + FIRMessagingAPNSTokenTypeProd, +} NS_SWIFT_NAME(MessagingAPNSTokenType); + +/// Information about a downstream message received by the app. +NS_SWIFT_NAME(MessagingMessageInfo) +@interface FIRMessagingMessageInfo : NSObject + +/// The status of the downstream message +@property(nonatomic, readonly, assign) FIRMessagingMessageStatus status; + +@end + +/** + * A remote data message received by the app via FCM (not just the APNs interface). + * + * This is only for devices running iOS 10 or above. To support devices running iOS 9 or below, use + * the local and remote notifications handlers defined in UIApplicationDelegate protocol. + */ +NS_SWIFT_NAME(MessagingRemoteMessage) +@interface FIRMessagingRemoteMessage : NSObject + +/// The message ID of downstream message. +@property(nonatomic, readonly, copy) NSString *messageID; +/// The downstream message received by the application. +@property(nonatomic, readonly, strong) NSDictionary *appData; + +@end + +@class FIRMessaging; +@class FIRMessagingExtensionHelper; + +/** + * A protocol to handle token update or data message delivery from FCM. + * + */ +NS_SWIFT_NAME(MessagingDelegate) +@protocol FIRMessagingDelegate + +@optional +/// This method will be called once a token is available, or has been refreshed. Typically it +/// will be called once per app start, but may be called more often, if token is invalidated or +/// updated. In this method, you should perform operations such as: +/// +/// * Uploading the FCM token to your application server, so targeted notifications can be sent. +/// +/// * Subscribing to any topics. +- (void)messaging:(FIRMessaging *)messaging + didReceiveRegistrationToken:(NSString *)fcmToken + NS_SWIFT_NAME(messaging(_:didReceiveRegistrationToken:)); + +/// Handle data messages received via FCM direct channel (not via APNS). +- (void)messaging:(FIRMessaging *)messaging + didReceiveMessage:(FIRMessagingRemoteMessage *)remoteMessage +NS_SWIFT_NAME(messaging(_:didReceive:)); + +@end + +/** + * Firebase Messaging lets you reliably deliver messages at no cost. + * + * To send or receive messages, the app must get a + * registration token from FIRInstanceID. This token authorizes an + * app server to send messages to an app instance. + * + * In order to receive FIRMessaging messages, declare + * `application:didReceiveRemoteNotification::fetchCompletionHandler:`. + */ +NS_SWIFT_NAME(Messaging) +@interface FIRMessaging : NSObject + +/** + * Delegate to handle FCM token refreshes, and remote data messages received via FCM direct channel. + */ +@property(nonatomic, weak, nullable) id delegate; + +/** + * When set to `YES`, Firebase Messaging will automatically establish a socket-based, direct + * channel to the FCM server. Enable this only if you are sending upstream messages or + * receiving non-APNS, data-only messages in foregrounded apps. + * Default is `NO`. + */ +@property(nonatomic) BOOL shouldEstablishDirectChannel; + +/** + * Returns `YES` if the direct channel to the FCM server is active, and `NO` otherwise. + */ +@property(nonatomic, readonly) BOOL isDirectChannelEstablished; + +/** + * FIRMessaging + * + * @return An instance of FIRMessaging. + */ ++ (instancetype)messaging NS_SWIFT_NAME(messaging()); + +/** + * FIRMessagingExtensionHelper + * + * Use FIRMessagingExtensionHelper to populate rich UI contents for your notifications. + * e.g. If an image URL is set in your notification payload or on the console, call + * FIRMessagingExtensionHelper API to render it on your notification. + * + * @return An instance of FIRMessagingExtensionHelper that handles the extensions API. + */ ++ (FIRMessagingExtensionHelper *)extensionHelper NS_SWIFT_NAME(serviceExtension()) NS_AVAILABLE_IOS(10.0); + +/** + * Unavailable. Use +messaging instead. + */ +- (instancetype)init __attribute__((unavailable("Use +messaging instead."))); + +#pragma mark - APNS + +/** + * This property is used to set the APNS Token received by the application delegate. + * + * FIRMessaging uses method swizzling to ensure that the APNS token is set + * automatically. However, if you have disabled swizzling by setting + * `FirebaseAppDelegateProxyEnabled` to `NO` in your app's + * Info.plist, you should manually set the APNS token in your application + * delegate's `-application:didRegisterForRemoteNotificationsWithDeviceToken:` + * method. + * + * If you would like to set the type of the APNS token, rather than relying on + * automatic detection, see: `-setAPNSToken:type:`. + */ +@property(nonatomic, copy, nullable) NSData *APNSToken NS_SWIFT_NAME(apnsToken); + +/** + * Set APNS token for the application. This APNS token will be used to register + * with Firebase Messaging using `FCMToken` or + * `tokenWithAuthorizedEntity:scope:options:handler`. + * + * @param apnsToken The APNS token for the application. + * @param type The type of APNS token. Debug builds should use + * FIRMessagingAPNSTokenTypeSandbox. Alternatively, you can supply + * FIRMessagingAPNSTokenTypeUnknown to have the type automatically + * detected based on your provisioning profile. + */ +- (void)setAPNSToken:(NSData *)apnsToken type:(FIRMessagingAPNSTokenType)type; + +#pragma mark - FCM Tokens + +/** + * Is Firebase Messaging token auto generation enabled? If this flag is disabled, + * Firebase Messaging will not generate token automatically for message delivery. + * + * If this flag is disabled, Firebase Messaging does not generate new tokens automatically for + * message delivery. If this flag is enabled, FCM generates a registration token on application + * start when there is no existing valid token. FCM also generates a new token when an existing + * token is deleted. + * + * This setting is persisted, and is applied on future + * invocations of your application. Once explicitly set, it overrides any + * settings in your Info.plist. + * + * By default, FCM automatic initialization is enabled. If you need to change the + * default (for example, because you want to prompt the user before getting token) + * set FirebaseMessagingAutoInitEnabled to false in your application's Info.plist. + */ +@property(nonatomic, assign, getter=isAutoInitEnabled) BOOL autoInitEnabled; + +/** + * The FCM token is used to identify this device so that FCM can send notifications to it. + * It is associated with your APNS token when the APNS token is supplied, so that sending + * messages to the FCM token will be delivered over APNS. + * + * The FCM token is sometimes refreshed automatically. In your FIRMessaging delegate, the + * delegate method `messaging:didReceiveRegistrationToken:` will be called once a token is + * available, or has been refreshed. Typically it should be called once per app start, but + * may be called more often, if token is invalidated or updated. + * + * Once you have an FCM token, you should send it to your application server, so it can use + * the FCM token to send notifications to your device. + */ +@property(nonatomic, readonly, nullable) NSString *FCMToken NS_SWIFT_NAME(fcmToken); + + +/** + * Retrieves an FCM registration token for a particular Sender ID. This can be used to allow + * multiple senders to send notifications to the same device. By providing a different Sender + * ID than your default when fetching a token, you can create a new FCM token which you can + * give to a different sender. Both tokens will deliver notifications to your device, and you + * can revoke a token when you need to. + * + * This registration token is not cached by FIRMessaging. FIRMessaging should have an APNS + * token set before calling this to ensure that notifications can be delivered via APNS using + * this FCM token. You may re-retrieve the FCM token once you have the APNS token set, to + * associate it with the FCM token. The default FCM token is automatically associated with + * the APNS token, if the APNS token data is available. + * + * @param senderID The Sender ID for a particular Firebase project. + * @param completion The completion handler to handle the token request. + */ +- (void)retrieveFCMTokenForSenderID:(NSString *)senderID + completion:(FIRMessagingFCMTokenFetchCompletion)completion + NS_SWIFT_NAME(retrieveFCMToken(forSenderID:completion:)); + + +/** + * Invalidates an FCM token for a particular Sender ID. That Sender ID cannot no longer send + * notifications to that FCM token. + * + * @param senderID The senderID for a particular Firebase project. + * @param completion The completion handler to handle the token deletion. + */ +- (void)deleteFCMTokenForSenderID:(NSString *)senderID + completion:(FIRMessagingDeleteFCMTokenCompletion)completion + NS_SWIFT_NAME(deleteFCMToken(forSenderID:completion:)); + +#pragma mark - Topics + +/** + * Asynchronously subscribes to a topic. + * + * @param topic The name of the topic, for example, @"sports". + */ +- (void)subscribeToTopic:(NSString *)topic NS_SWIFT_NAME(subscribe(toTopic:)); + +/** + * Asynchronously subscribe to the provided topic, retrying on failure. + * + * @param topic The topic name to subscribe to, for example, @"sports". + * @param completion The completion that is invoked once the subscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)subscribeToTopic:(nonnull NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion; + +/** + * Asynchronously unsubscribe from a topic. + * + * @param topic The name of the topic, for example @"sports". + */ +- (void)unsubscribeFromTopic:(NSString *)topic NS_SWIFT_NAME(unsubscribe(fromTopic:)); + +/** + * Asynchronously unsubscribe from the provided topic, retrying on failure. + * + * @param topic The topic name to unsubscribe from, for example @"sports". + * @param completion The completion that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)unsubscribeFromTopic:(nonnull NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion; + +#pragma mark - Upstream + +/** + * Sends an upstream ("device to cloud") message. + * + * The message is queued if we don't have an active connection. + * You can only use the upstream feature if your FCM implementation + * uses the XMPP server protocol. + * + * @param message Key/Value pairs to be sent. Values must be String, any + * other type will be ignored. + * @param receiver A string identifying the receiver of the message. For FCM + * project IDs the value is `SENDER_ID@gcm.googleapis.com`. + * @param messageID The ID of the message. This is generated by the application. It + * must be unique for each message generated by this application. + * It allows error callbacks and debugging, to uniquely identify + * each message. + * @param ttl The time to live for the message. In case we aren't able to + * send the message before the TTL expires we will send you a + * callback. If 0, we'll attempt to send immediately and return + * an error if we're not connected. Otherwise, the message will + * be queued. As for server-side messages, we don't return an error + * if the message has been dropped because of TTL; this can happen + * on the server side, and it would require extra communication. + */ +- (void)sendMessage:(NSDictionary *)message + to:(NSString *)receiver + withMessageID:(NSString *)messageID + timeToLive:(int64_t)ttl; + +#pragma mark - Analytics + +/** + * Use this to track message delivery and analytics for messages, typically + * when you receive a notification in `application:didReceiveRemoteNotification:`. + * However, you only need to call this if you set the `FirebaseAppDelegateProxyEnabled` + * flag to `NO` in your Info.plist. If `FirebaseAppDelegateProxyEnabled` is either missing + * or set to `YES` in your Info.plist, the library will call this automatically. + * + * @param message The downstream message received by the application. + * + * @return Information about the downstream message. + */ +- (FIRMessagingMessageInfo *)appDidReceiveMessage:(NSDictionary *)message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessagingExtensionHelper.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessagingExtensionHelper.h new file mode 100644 index 0000000..f50478e --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessagingExtensionHelper.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +#import +#endif + + NS_ASSUME_NONNULL_BEGIN + + __IOS_AVAILABLE(10.0) +@interface FIRMessagingExtensionHelper : NSObject + + /// Call this API to complete your notification content modification. If you like to +/// overwrite some properties of the content instead of using the default payload, +/// make sure to make your customized motification to the content before passing it to +/// this call. +- (void)populateNotificationContent:(UNMutableNotificationContent *)content + withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler; + + @end + + NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FirebaseMessaging.h b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FirebaseMessaging.h new file mode 100755 index 0000000..c5d0bd0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FirebaseMessaging.h @@ -0,0 +1,18 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" +#import "FIRMessagingExtensionHelper.h" diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/LICENSE b/PRODUCTNAME/app/Pods/FirebaseMessaging/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PRODUCTNAME/app/Pods/FirebaseMessaging/README.md b/PRODUCTNAME/app/Pods/FirebaseMessaging/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/FirebaseMessaging/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Libraries/libGoogleAnalytics.a b/PRODUCTNAME/app/Pods/GoogleAnalytics/Libraries/libGoogleAnalytics.a deleted file mode 100755 index 0b55587..0000000 Binary files a/PRODUCTNAME/app/Pods/GoogleAnalytics/Libraries/libGoogleAnalytics.a and /dev/null differ diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAI.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAI.h deleted file mode 100755 index af16ad2..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAI.h +++ /dev/null @@ -1,192 +0,0 @@ -/*! - @header GAI.h - @abstract Google Analytics iOS SDK Header - @version 3.17 - @copyright Copyright 2015 Google Inc. All rights reserved. - */ - -#import - -#import "GAILogger.h" -#import "GAITrackedViewController.h" -#import "GAITracker.h" - -typedef NS_ENUM(NSUInteger, GAIDispatchResult) { - kGAIDispatchNoData, - kGAIDispatchGood, - kGAIDispatchError -}; - -/*! Google Analytics product string. */ -extern NSString *const kGAIProduct; - -/*! Google Analytics version string. */ -extern NSString *const kGAIVersion; - -/*! - NSError objects returned by the Google Analytics SDK may have this error domain - to indicate that the error originated in the Google Analytics SDK. - */ -extern NSString *const kGAIErrorDomain; - -/*! Google Analytics error codes. */ -typedef enum { - // This error code indicates that there was no error. Never used. - kGAINoError = 0, - - // This error code indicates that there was a database-related error. - kGAIDatabaseError, - - // This error code indicates that there was a network-related error. - kGAINetworkError, -} GAIErrorCode; - -/*! - Google Analytics iOS top-level class. Provides facilities to create trackers - and set behaviorial flags. - */ -@interface GAI : NSObject - -/*! - For convenience, this class exposes a default tracker instance. - This is initialized to `nil` and will be set to the first tracker that is - instantiated in trackerWithTrackingId:. It may be overridden as desired. - - The GAITrackedViewController class will, by default, use this tracker instance. - */ -@property(nonatomic, assign) id defaultTracker; - -/*! - The GAILogger to use. - */ -@property(nonatomic, retain) id logger; - -/*! - When this is true, no tracking information will be gathered; tracking calls - will effectively become no-ops. When set to true, all tracking information that - has not yet been submitted. The value of this flag will be persisted - automatically by the SDK. Developers can optionally use this flag to implement - an opt-out setting in the app to allows users to opt out of Google Analytics - tracking. - - This is set to `NO` the first time the Google Analytics SDK is used on a - device, and is persisted thereafter. - */ -@property(nonatomic, assign) BOOL optOut; - -/*! - If this value is positive, tracking information will be automatically - dispatched every dispatchInterval seconds. Otherwise, tracking information must - be sent manually by calling dispatch. - - By default, this is set to `120`, which indicates tracking information should - be dispatched automatically every 120 seconds. - */ -@property(nonatomic, assign) NSTimeInterval dispatchInterval; - -/*! - When set to true, the SDK will record the currently registered uncaught - exception handler, and then register an uncaught exception handler which tracks - the exceptions that occurred using defaultTracker. If defaultTracker is not - `nil`, this function will track the exception on the tracker and attempt to - dispatch any outstanding tracking information for 5 seconds. It will then call - the previously registered exception handler, if any. When set back to false, - the previously registered uncaught exception handler will be restored. - */ -@property(nonatomic, assign) BOOL trackUncaughtExceptions; - -/*! - When this is 'YES', no tracking information will be sent. Defaults to 'NO'. - */ -@property(nonatomic, assign) BOOL dryRun; - -/*! Get the shared instance of the Google Analytics for iOS class. */ -+ (GAI *)sharedInstance; - -/*! - Creates or retrieves a GAITracker implementation with the specified name and - tracking ID. If the tracker for the specified name does not already exist, then - it will be created and returned; otherwise, the existing tracker will be - returned. If the existing tracker for the respective name has a different - tracking ID, that tracking ID is not changed by this method. If defaultTracker - is not set, it will be set to the tracker instance returned here. - - @param name The name of this tracker. Must not be `nil` or empty. - - @param trackingID The tracking ID to use for this tracker. It should be of - the form `UA-xxxxx-y`. - - @return A GAITracker associated with the specified name. The tracker - can be used to send tracking data to Google Analytics. The first time this - method is called with a particular name, the tracker for that name will be - returned, and subsequent calls with the same name will return the same - instance. It is not necessary to retain the tracker because the tracker will be - retained internally by the library. - - If an error occurs or the name is not valid, this method will return - `nil`. - */ -- (id)trackerWithName:(NSString *)name - trackingId:(NSString *)trackingId; - -/*! - Creates or retrieves a GAITracker implementation with name equal to - the specified tracking ID. If the tracker for the respective name does not - already exist, it is created, has it's tracking ID set to |trackingId|, - and is returned; otherwise, the existing tracker is returned. If the existing - tracker for the respective name has a different tracking ID, that tracking ID - is not changed by this method. If defaultTracker is not set, it is set to the - tracker instance returned here. - - @param trackingID The tracking ID to use for this tracker. It should be of - the form `UA-xxxxx-y`. The name of the tracker will be the same as trackingID. - - @return A GAITracker associated with the specified trackingID. The tracker - can be used to send tracking data to Google Analytics. The first time this - method is called with a particular trackingID, the tracker for the respective - name will be returned, and subsequent calls with the same trackingID - will return the same instance. It is not necessary to retain the tracker - because the tracker will be retained internally by the library. - - If an error occurs or the trackingId is not valid, this method will return - `nil`. - */ -- (id)trackerWithTrackingId:(NSString *)trackingId; - -/*! - Remove a tracker from the trackers dictionary. If it is the default tracker, - clears the default tracker as well. - - @param name The name of the tracker. - */ -- (void)removeTrackerByName:(NSString *)name; - -/*! - Dispatches any pending tracking information. - - Note that this does not have any effect on dispatchInterval, and can be used in - conjunction with periodic dispatch. */ -- (void)dispatch; - -/*! - Dispatches the next tracking beacon in the queue, calling completionHandler when - the tracking beacon has either been sent (returning kGAIDispatchGood) or an error has resulted - (returning kGAIDispatchError). If there is no network connection or there is no data to send, - kGAIDispatchNoData is returned. - - Note that calling this method with a non-nil completionHandler disables periodic dispatch. - Periodic dispatch can be reenabled by setting the dispatchInterval to a positive number when - the app resumes from the background. - - Calling this method with a nil completionHandler is the same as calling the dispatch - above. - - This method can be used for background data fetching in iOS 7.0 or later. It would be wise to - call this when the application is exiting to initiate the submission of any unsubmitted - tracking information. - - @param completionHandler The block to run after a single dispatch request. The GAIDispatchResult - param indicates whether the dispatch succeeded, had an error, or had no hits to dispatch. - */ -- (void)dispatchWithCompletionHandler:(void (^)(GAIDispatchResult result))completionHandler; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIDictionaryBuilder.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIDictionaryBuilder.h deleted file mode 100755 index d3e053d..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIDictionaryBuilder.h +++ /dev/null @@ -1,214 +0,0 @@ -/*! - @header GAIDictionaryBuilder.h - @abstract Google Analytics iOS SDK Hit Format Header - @copyright Copyright 2013 Google Inc. All rights reserved. - */ - -#import - -#import "GAIEcommerceProduct.h" -#import "GAIEcommerceProductAction.h" -#import "GAIEcommercePromotion.h" - -/*! - * Helper class to build a dictionary of hit parameters and values. - *
- * Examples: - * - * id t = // get a tracker. - * [t send:[[[GAIDictionaryBuilder createEventWithCategory:@"EventCategory" - * action:@"EventAction" - * label:nil - * value:nil] - * set:@"dimension1" forKey:[GAIFields customDimensionForIndex:1]] build]]; - * - * This will send an event hit type with the specified parameters - * and a custom dimension parameter. - *
- * If you want to send a parameter with all hits, set it on GAITracker directly. - * - * [t set:kGAIScreenName value:@"Home"]; - * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+" - * action:@"PlusOne" - * target:@"SOME_URL"] build]]; - * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+" - * action:@"Share" - * target:@"SOME_POST"] build]]; - * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+" - * action:@"HangOut" - * target:@"SOME_CIRCLE"] - * build]]; - * - * You can override a value set on the tracker by adding it to the dictionary. - * - * [t set:kGAIScreenName value:@"Home"]; - * [t send:...]; - * [t send[[[GAIDictionaryBuilder createEventWithCategory:@"click" - * action:@"popup" - * label:nil - * value:nil] - * set:@"popup title" forKey:kGAIScreenName] build]]; - * - * The values set via [GAIDictionaryBuilder set] or - * [GAIDictionaryBuilder setAll] will override any existing values in the - * GAIDictionaryBuilder object (i.e. initialized by - * [GAIDictionaryBuilder createXYZ]). e.g. - * - * GAIDictionaryBuilder *m = - * GAIDictionaryBuilder createTimingWithCategory:@"category" - * interval:@0 - * name:@"name" - * label:nil]; - * [t send:[m.set:@"10" forKey:kGAITimingVar] build]; - * [t send:[m.set:@"20" forKey:kGAITimingVar] build]; - * - */ -@interface GAIDictionaryBuilder : NSObject - -- (GAIDictionaryBuilder *)set:(NSString *)value - forKey:(NSString *)key; - -/*! - * Copies all the name-value pairs from params into this object, ignoring any - * keys that are not NSString and any values that are neither NSString or - * NSNull. - */ -- (GAIDictionaryBuilder *)setAll:(NSDictionary *)params; - -/*! - * Returns the value for the input parameter paramName, or nil if paramName - * is not present. - */ -- (NSString *)get:(NSString *)paramName; - -/*! - * Return an NSMutableDictionary object with all the parameters set in this - */ -- (NSMutableDictionary *)build; - -/*! - * Parses and translates utm campaign parameters to analytics campaign param - * and returns them as a map. - * - * @param params url containing utm campaign parameters. - * - * Valid campaign parameters are: - *
    - *
  • utm_id
  • - *
  • utm_campaign
  • - *
  • utm_content
  • - *
  • utm_medium
  • - *
  • utm_source
  • - *
  • utm_term
  • - *
  • dclid
  • - *
  • gclid
  • - *
  • gmob_t
  • - *
  • aclid
  • - *
  • anid
  • - *
- *

- * Example: - * http://my.site.com/index.html?utm_campaign=wow&utm_source=source - * utm_campaign=wow&utm_source=source. - *

- * For more information on manual and auto-tagging, see - * https://support.google.com/analytics/answer/1733663?hl=en - */ -- (GAIDictionaryBuilder *)setCampaignParametersFromUrl:(NSString *)urlString; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to an appview - hit. - - Note that using this method will not set the screen name for followon hits. To - do that you need to call set:kGAIDescription value: on the - GAITracker instance. - - This method is deprecated. Use createScreenView instead. - */ -+ (GAIDictionaryBuilder *)createAppView DEPRECATED_MSG_ATTRIBUTE("Use createScreenView instead."); - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to a screenview - hit. - - Note that using this method will not set the screen name for followon hits. To - do that you need to call set:kGAIDescription value: on the - GAITracker instance. - */ -+ (GAIDictionaryBuilder *)createScreenView; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to an event hit. - */ -+ (GAIDictionaryBuilder *)createEventWithCategory:(NSString *)category - action:(NSString *)action - label:(NSString *)label - value:(NSNumber *)value; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to an exception - hit. - */ -+ (GAIDictionaryBuilder *)createExceptionWithDescription:(NSString *)description - withFatal:(NSNumber *)fatal; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to an item hit. - */ -+ (GAIDictionaryBuilder *)createItemWithTransactionId:(NSString *)transactionId - name:(NSString *)name - sku:(NSString *)sku - category:(NSString *)category - price:(NSNumber *)price - quantity:(NSNumber *)quantity - currencyCode:(NSString *)currencyCode; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to a social hit. - */ -+ (GAIDictionaryBuilder *)createSocialWithNetwork:(NSString *)network - action:(NSString *)action - target:(NSString *)target; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to a timing hit. - */ -+ (GAIDictionaryBuilder *)createTimingWithCategory:(NSString *)category - interval:(NSNumber *)intervalMillis - name:(NSString *)name - label:(NSString *)label; - -/*! - Returns a GAIDictionaryBuilder object with parameters specific to a transaction - hit. - */ -+ (GAIDictionaryBuilder *)createTransactionWithId:(NSString *)transactionId - affiliation:(NSString *)affiliation - revenue:(NSNumber *)revenue - tax:(NSNumber *)tax - shipping:(NSNumber *)shipping - currencyCode:(NSString *)currencyCode; - -/*! - Set the product action field for this hit. - */ -- (GAIDictionaryBuilder *)setProductAction:(GAIEcommerceProductAction *)productAction; - -/*! - Adds a product to this hit. - */ -- (GAIDictionaryBuilder *)addProduct:(GAIEcommerceProduct *)product; - -/*! - Add a product impression to this hit. - */ -- (GAIDictionaryBuilder *)addProductImpression:(GAIEcommerceProduct *)product - impressionList:(NSString *)name - impressionSource:(NSString *)source; - -/*! - Add a promotion to this hit. - */ -- (GAIDictionaryBuilder *)addPromotion:(GAIEcommercePromotion *)promotion; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceFields.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceFields.h deleted file mode 100755 index b3ba60a..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceFields.h +++ /dev/null @@ -1,124 +0,0 @@ -/*! - @header GAIEcommerceFields.h - @abstract Google Analytics iOS SDK Ecommerce Hit Format Header - @copyright Copyright 2014 Google Inc. All rights reserved. - */ - -#import - -/*! - This class provides several fields and methods useful as wire format parameters for - Enhanced Ecommerce. See the online developer guides for Enhanced Ecommerce for details - on how to use the Enhanced Ecommerce features. - */ - -// Enhanced Ecommerce Product fields -extern NSString *const kGAIProductId; -extern NSString *const kGAIProductName; -extern NSString *const kGAIProductBrand; -extern NSString *const kGAIProductCategory; -extern NSString *const kGAIProductVariant; -extern NSString *const kGAIProductPrice; -extern NSString *const kGAIProductQuantity; -extern NSString *const kGAIProductCouponCode; -extern NSString *const kGAIProductPosition; - -extern NSString *const kGAIProductAction; - -// product action values -extern NSString *const kGAIPADetail; -extern NSString *const kGAIPAClick; -extern NSString *const kGAIPAAdd; -extern NSString *const kGAIPARemove; -extern NSString *const kGAIPACheckout; -extern NSString *const kGAIPACheckoutOption; -extern NSString *const kGAIPAPurchase; -extern NSString *const kGAIPARefund; - -// product action fields -// used for 'purchase' and 'refund' actions -extern NSString *const kGAIPATransactionId; -extern NSString *const kGAIPAAffiliation; -extern NSString *const kGAIPARevenue; -extern NSString *const kGAIPATax; -extern NSString *const kGAIPAShipping; -extern NSString *const kGAIPACouponCode; -// used for 'checkout' action -extern NSString *const kGAICheckoutStep; -extern NSString *const kGAICheckoutOption; -// used for 'detail' and 'click' actions -extern NSString *const kGAIProductActionList; -extern NSString *const kGAIProductListSource; - -// Enhanced Ecommerce Impressions fields -extern NSString *const kGAIImpressionName; -extern NSString *const kGAIImpressionListSource; -extern NSString *const kGAIImpressionProduct; -extern NSString *const kGAIImpressionProductId; -extern NSString *const kGAIImpressionProductName; -extern NSString *const kGAIImpressionProductBrand; -extern NSString *const kGAIImpressionProductCategory; -extern NSString *const kGAIImpressionProductVariant; -extern NSString *const kGAIImpressionProductPosition; -extern NSString *const kGAIImpressionProductPrice; - -// Enhanced Ecommerce Promotions fields -extern NSString *const kGAIPromotionId; -extern NSString *const kGAIPromotionName; -extern NSString *const kGAIPromotionCreative; -extern NSString *const kGAIPromotionPosition; - -// Promotion actions -extern NSString *const kGAIPromotionAction; -extern NSString *const kGAIPromotionView; -extern NSString *const kGAIPromotionClick; - -@interface GAIEcommerceFields : NSObject - -/*! - Generates an enhanced ecommerce product field. Note that field names generated by - customDimensionForIndex and customMetricForIndex can be used as suffixes. - - @param index the index of the product - @param suffix the product field suffix (such as kGAIProductPrice). - - @return an NSString representing the product field parameter - */ -+ (NSString *)productFieldForIndex:(NSUInteger)index suffix:(NSString *)suffix; - -/*! - Genrates an enhanced ecommerce impression list field name with an index. The return value of - this method should also be used as input to the productImpressionForList method below. - - @param index the index of the impression list - - @return an NSString representing the impression list parameter - */ -+ (NSString *)impressionListForIndex:(NSUInteger)index; - -/*! - Generates an enhanced ecommerce product impression field with the impression list, product index - and product suffix as parameters. The output of the method impressionListForIndex above should be - used as the input list for this method. The output of customDimensionForIndex and - customMetricForIndex can be used as suffixes. - - @param list the impression list for this product impression - @param index the index of this product in the impression list - @param suffix the product impression suffix for this field - - @return an NSString representing this product impression field parameter - */ -+ (NSString *)productImpressionForList:(NSString *)list - index:(NSUInteger)index - suffix:(NSString *)Suffix; - -/*! - Generates an enhanced ecommerce promotion field with an index and suffix. - - @param index the index of the promotion - @param suffix the promotion suffix (such as kGAIPromotionId) - - @return an NSString representing this promotion field paramter - */ -+ (NSString *)promotionForIndex:(NSUInteger)index suffix:(NSString *)suffix; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceProduct.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceProduct.h deleted file mode 100755 index 029f763..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceProduct.h +++ /dev/null @@ -1,102 +0,0 @@ -/*! - @header GAIEcommerceProduct.h - @abstract Google Analytics iOS SDK Hit Format Header - @copyright Copyright 2014 Google Inc. All rights reserved. - */ - -#import - -/*! - * Class to construct product related information for a Google Analytics beacon. Use this class to - * report information about products sold by merchants or impressions of products seen by users. - * Instances of this class can be associated with both Product Actions and Product - * Impression Lists. - *
- * Typical usage: - * - * [tracker set:kGAIScreenName value:@"MyScreen"]; - * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView]; - * GAIEcommerceProduct *product = [[GAIEcommerceProduct alloc] init]; - * [product setId:@""PID-1234""]; - * [product setName:@"Space Monkeys!"]; - * [product setPrice:@100]; - * [product setQuantity:@2]; - * [builder addProductImpression:product impressionList:@"listName"]; - * [tracker send:[builder build]]; - * - */ -@interface GAIEcommerceProduct : NSObject - -/*! - Sets the id that is used to identify a product in GA reports. - */ -- (GAIEcommerceProduct *)setId:(NSString *)productId; - -/*! - Sets the name that is used to indentify the product in GA reports. - */ -- (GAIEcommerceProduct *)setName:(NSString *)productName; - -/*! - Sets the brand associated with the product in GA reports. - */ -- (GAIEcommerceProduct *)setBrand:(NSString *)productBrand; - -/*! - Sets the category associated with the product in GA reports. - */ -- (GAIEcommerceProduct *)setCategory:(NSString *)productCategory; - -/*! - Sets the variant of the product. - */ -- (GAIEcommerceProduct *)setVariant:(NSString *)productVariant; - -/*! - Sets the price of the product. - */ -- (GAIEcommerceProduct *)setPrice:(NSNumber *)productPrice; - -/*! - Sets the quantity of the product. This field is usually not used with product impressions. - */ -- (GAIEcommerceProduct *)setQuantity:(NSNumber *)productQuantity; - -/*! - Sets the coupon code associated with the product. This field is usually not used with product - impressions. - */ -- (GAIEcommerceProduct *)setCouponCode:(NSString *)productCouponCode; - -/*! - Sets the position of the product on the screen/product impression list, etc. - */ -- (GAIEcommerceProduct *)setPosition:(NSNumber *)productPosition; - -/*! - Sets the custom dimension associated with this product. - */ -- (GAIEcommerceProduct *)setCustomDimension:(NSUInteger)index value:(NSString *)value; - -/*! - Sets the custom metric associated with this product. - */ -- (GAIEcommerceProduct *)setCustomMetric:(NSUInteger)index value:(NSNumber *)value; - -/*! - Builds an NSDictionary of fields stored in this instance suitable for a product action. The - index parameter is the index of this product in the product action list. -
- Normally, users will have no need to call this method. - */ -- (NSDictionary *)buildWithIndex:(NSUInteger)index; - -/*! - Builds an NSDictionary of fields stored in this instance suitable for an impression list. The - lIndex parameter is the index of the product impression list while the index parameter is the - index of this product in that impression list. -
- Normally, users will have no need to call this method. - */ -- (NSDictionary *)buildWithListIndex:(NSUInteger)lIndex index:(NSUInteger)index; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceProductAction.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceProductAction.h deleted file mode 100755 index e3da1c1..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommerceProductAction.h +++ /dev/null @@ -1,107 +0,0 @@ -/*! - @header GAIProductAction.h - @abstract Google Analytics iOS SDK Hit Format Header - @copyright Copyright 2014 Google Inc. All rights reserved. - */ - -#import - -/*! - * Class to construct transaction/checkout or other product interaction related information for a - * Google Analytics hit. Use this class to report information about products sold, viewed or - * refunded. This class is intended to be used with GAIDictionaryBuilder. - *
- * Typical usage: - * - * [tracker set:kGAIScreenName value:@"MyScreen"]; - * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView]; - * GAIEcommerceProductAction *action = [[GAIEcommerceProductAction alloc] init]; - * [action setAction:kGAIPAPurchase]; - * [action setTransactionId:@"TT-1234"]; - * [action setRevenue:@3.14]; - * [action setCouponCode:@"EXTRA100"]; - * [builder setProductAction:action]; - * GAIEcommerceProduct *product = [[GAIEcommerceProduct alloc] init]; - * [product setId:@""PID-1234""]; - * [product setName:@"Space Monkeys!"]; - * [product setPrice:@100]; - * [product setQuantity:@2]; - * [builder addProduct:product]; - * [tracker send:[builder build]]; - * - */ -@interface GAIEcommerceProductAction : NSObject - -/*! - Sets the product action field for this product action. Valid values can be found in - GAIEcommerceFields.h under "product action values". - */ -- (GAIEcommerceProductAction *)setAction:(NSString *)productAction; - -/*! - The unique id associated with the transaction. This value is used for kGAIPAPurchase and - kGAIPARefund product actions. - */ -- (GAIEcommerceProductAction *)setTransactionId:(NSString *)transactionId; - -/*! - Sets the transaction's affiliation value. This value is used for kGAIPAPurchase and - kGAIPARefund product actions. - */ -- (GAIEcommerceProductAction *)setAffiliation:(NSString *)affiliation; - -/*! - Sets the transaction's total revenue. This value is used for kGAIPAPurchase and kGAIPARefund - product actions. - */ -- (GAIEcommerceProductAction *)setRevenue:(NSNumber *)revenue; - -/*! - Sets the transaction's total tax. This value is used for kGAIPAPurchase and kGAIPARefund - product actions. - */ -- (GAIEcommerceProductAction *)setTax:(NSNumber *)tax; - -/*! - Sets the transaction's total shipping costs. This value is used for kGAIPAPurchase and - kGAIPARefund product actions. - */ -- (GAIEcommerceProductAction *)setShipping:(NSNumber *)shipping; - -/*! - Sets the coupon code used in this transaction. This value is used for kGAIPAPurchase and - kGAIPARefund product actions. - */ -- (GAIEcommerceProductAction *)setCouponCode:(NSString *)couponCode; - -/*! - Sets the checkout process's progress. This value is used for kGAICheckout and - kGAICheckoutOptions product actions. - */ -- (GAIEcommerceProductAction *)setCheckoutStep:(NSNumber *)checkoutStep; - -/*! - Sets the option associated with the checkout. This value is used for kGAICheckout and - kGAICheckoutOptions product actions. - */ -- (GAIEcommerceProductAction *)setCheckoutOption:(NSString *)checkoutOption; - -/*! - Sets the list name associated with the products in Google Analytics beacons. This value is - used in kGAIPADetail and kGAIPAClick product actions. - */ -- (GAIEcommerceProductAction *)setProductActionList:(NSString *)productActionList; - -/*! - Sets the list source name associated with the products in Google Analytics beacons. This value - is used in kGAIPADetail and kGAIPAClick product actions. - */ -- (GAIEcommerceProductAction *)setProductListSource:(NSString *)productListSource; - -/*! - Builds an NSDictionary of fields stored in this instance representing this product action. -
- Normally, users will have no need to call this method. - */ -- (NSDictionary *)build; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommercePromotion.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommercePromotion.h deleted file mode 100755 index c7bf25a..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIEcommercePromotion.h +++ /dev/null @@ -1,54 +0,0 @@ -/*! - @header GAIEcommercePromotion.h - @abstract Google Analytics iOS SDK Hit Format Header - @copyright Copyright 2014 Google Inc. All rights reserved. - */ - -#import - -/*! - * Class to construct promotion related fields for Google Analytics hits. The fields from this class - * can be used to represent internal promotions that run within an app, such as banners, banner ads - * etc. - * - * Typical usage: - * - * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView]; - * GAIEcommercePromotion *promotion = [[GAIEcommercePromotion alloc] init]; - * [promotion setId:@"PROMO-ID1234"]; - * [promotion setName:@"Home screen banner"]; - * [builder set:kGAIPromotionClick forKey:kGAIPromotionAction]; - * [builder addPromotion:promotion]; - * [tracker send:builder.build]]; - * - */ -@interface GAIEcommercePromotion : NSObject - -/*! - Sets the id that is used to identify a promotion in GA reports. - */ -- (GAIEcommercePromotion *)setId:(NSString *)pid; - -/*! - Sets the name that is used to identify a promotion in GA reports. - */ -- (GAIEcommercePromotion *)setName:(NSString *)name; - -/*! - Sets the name of the creative associated with the promotion. - */ -- (GAIEcommercePromotion *)setCreative:(NSString *)creative; - -/*! - Sets the position of the promotion. - */ -- (GAIEcommercePromotion *)setPosition:(NSString *)position; - -/*! - Builds an NSDictionary of fields stored in this instance. The index parameter is the - index of this promotion in that promotion list. -
- Normally, users will have no need to call this method. - */ -- (NSDictionary *)buildWithIndex:(NSUInteger)index; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIFields.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIFields.h deleted file mode 100755 index e54cef0..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAIFields.h +++ /dev/null @@ -1,133 +0,0 @@ -/*! - @header GAIFields.h - @abstract Google Analytics iOS SDK Hit Format Header - @copyright Copyright 2013 Google Inc. All rights reserved. - */ - -#import - -/*! - These fields can be used for the wire format parameter names required by - the |GAITracker| get, set and send methods as well as the set methods in the - |GAIDictionaryBuilder| class. - */ -extern NSString *const kGAIUseSecure; - -extern NSString *const kGAIHitType; -extern NSString *const kGAITrackingId; -extern NSString *const kGAIClientId; -extern NSString *const kGAIDataSource; -extern NSString *const kGAIAnonymizeIp; -extern NSString *const kGAISessionControl; -extern NSString *const kGAIDeviceModelVersion; -extern NSString *const kGAIScreenResolution; -extern NSString *const kGAIViewportSize; -extern NSString *const kGAIEncoding; -extern NSString *const kGAIScreenColors; -extern NSString *const kGAILanguage; -extern NSString *const kGAIJavaEnabled; -extern NSString *const kGAIFlashVersion; -extern NSString *const kGAINonInteraction; -extern NSString *const kGAIReferrer; -extern NSString *const kGAILocation; -extern NSString *const kGAIHostname; -extern NSString *const kGAIPage; -extern NSString *const kGAIDescription; // synonym for kGAIScreenName -extern NSString *const kGAIScreenName; // synonym for kGAIDescription -extern NSString *const kGAITitle; -extern NSString *const kGAIAdMobHitId; -extern NSString *const kGAIAppName; -extern NSString *const kGAIAppVersion; -extern NSString *const kGAIAppId; -extern NSString *const kGAIAppInstallerId; -extern NSString *const kGAIUserId; - -extern NSString *const kGAIEventCategory; -extern NSString *const kGAIEventAction; -extern NSString *const kGAIEventLabel; -extern NSString *const kGAIEventValue; - -extern NSString *const kGAISocialNetwork; -extern NSString *const kGAISocialAction; -extern NSString *const kGAISocialTarget; - -extern NSString *const kGAITransactionId; -extern NSString *const kGAITransactionAffiliation; -extern NSString *const kGAITransactionRevenue; -extern NSString *const kGAITransactionShipping; -extern NSString *const kGAITransactionTax; -extern NSString *const kGAICurrencyCode; - -extern NSString *const kGAIItemPrice; -extern NSString *const kGAIItemQuantity; -extern NSString *const kGAIItemSku; -extern NSString *const kGAIItemName; -extern NSString *const kGAIItemCategory; - -extern NSString *const kGAICampaignSource; -extern NSString *const kGAICampaignMedium; -extern NSString *const kGAICampaignName; -extern NSString *const kGAICampaignKeyword; -extern NSString *const kGAICampaignContent; -extern NSString *const kGAICampaignId; -extern NSString *const kGAICampaignAdNetworkClickId; -extern NSString *const kGAICampaignAdNetworkId; - -extern NSString *const kGAITimingCategory; -extern NSString *const kGAITimingVar; -extern NSString *const kGAITimingValue; -extern NSString *const kGAITimingLabel; - -extern NSString *const kGAIExDescription; -extern NSString *const kGAIExFatal; - -extern NSString *const kGAISampleRate; - -extern NSString *const kGAIIdfa; -extern NSString *const kGAIAdTargetingEnabled; - -// hit types -extern NSString *const kGAIAppView DEPRECATED_MSG_ATTRIBUTE("Use kGAIScreenView instead."); -extern NSString *const kGAIScreenView; -extern NSString *const kGAIEvent; -extern NSString *const kGAISocial; -extern NSString *const kGAITransaction; -extern NSString *const kGAIItem; -extern NSString *const kGAIException; -extern NSString *const kGAITiming; - -/*! - This class provides several fields and methods useful as wire format parameter - names. The methods are used for wire format parameter names that are indexed. - */ - -@interface GAIFields : NSObject - -/*! - Generates the correct parameter name for a content group with an index. - - @param index the index of the content group. - - @return an NSString representing the content group parameter for the index. - */ -+ (NSString *)contentGroupForIndex:(NSUInteger)index; - -/*! - Generates the correct parameter name for a custon dimension with an index. - - @param index the index of the custom dimension. - - @return an NSString representing the custom dimension parameter for the index. - */ -+ (NSString *)customDimensionForIndex:(NSUInteger)index; - -/*! - Generates the correct parameter name for a custom metric with an index. - - @param index the index of the custom metric. - - @return an NSString representing the custom metric parameter for the index. - */ -+ (NSString *)customMetricForIndex:(NSUInteger)index; - -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAILogger.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAILogger.h deleted file mode 100755 index 06291f2..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAILogger.h +++ /dev/null @@ -1,49 +0,0 @@ -/*! - @header GAILogger.h - @abstract Google Analytics iOS SDK Source - @copyright Copyright 2011 Google Inc. All rights reserved. - */ - -#import - -typedef NS_ENUM(NSUInteger, GAILogLevel) { - kGAILogLevelNone = 0, - kGAILogLevelError = 1, - kGAILogLevelWarning = 2, - kGAILogLevelInfo = 3, - kGAILogLevelVerbose = 4 -}; - -/*! - Protocol to be used for logging debug and informational messages from the SDK. - Implementations of this protocol can be provided to the |GAI| class, - to be used as the logger by the SDK. See the |logger| property in GAI.h. - */ -@protocol GAILogger -@required - -/*! - Only messages of |logLevel| and below are logged. - */ -@property (nonatomic, assign) GAILogLevel logLevel; - -/*! - Logs message with log level |kGAILogLevelVerbose|. - */ -- (void)verbose:(NSString *)message; - -/*! - Logs message with log level |kGAILogLevelInfo|. - */ -- (void)info:(NSString *)message; - -/*! - Logs message with log level |kGAILogLevelWarning|. - */ -- (void)warning:(NSString *)message; - -/*! - Logs message with log level |kGAILogLevelError|. - */ -- (void)error:(NSString *)message; -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAITrackedViewController.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAITrackedViewController.h deleted file mode 100755 index de19def..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAITrackedViewController.h +++ /dev/null @@ -1,33 +0,0 @@ -/*! - @header GAITrackedViewController.h - @abstract Google Analytics for iOS Tracked View Controller Header - @copyright Copyright 2012 Google Inc. All rights reserved. - */ - -#import -#import - -@protocol GAITracker; - -/*! - Extends UIViewController to generate Google Analytics screenview calls - whenever the view appears; this is done by overriding the `viewDidAppear:` - method. The screen name must be set for any tracking calls to be made. - - By default, this will use [GAI defaultTracker] for tracking calls, but one can - override this by setting the tracker property. - */ -@interface GAITrackedViewController : UIViewController - -/*! - The tracker on which view tracking calls are be made, or `nil`, in which case - [GAI defaultTracker] will be used. - */ -@property(nonatomic, assign) id tracker; -/*! - The screen name, for purposes of Google Analytics tracking. If this is `nil`, - no tracking calls will be made. - */ -@property(nonatomic, copy) NSString *screenName; - -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAITracker.h b/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAITracker.h deleted file mode 100755 index fdc5c5d..0000000 --- a/PRODUCTNAME/app/Pods/GoogleAnalytics/Sources/GAITracker.h +++ /dev/null @@ -1,57 +0,0 @@ -/*! - @header GAITracker.h - @abstract Google Analytics iOS SDK Tracker Header - @copyright Copyright 2013 Google Inc. All rights reserved. -*/ - -#import - -/*! - Google Analytics tracking interface. Obtain instances of this interface from - [GAI trackerWithTrackingId:] to track screens, events, transactions, timing, - and exceptions. The implementation of this interface is thread-safe, and no - calls are expected to block or take a long time. All network and disk activity - will take place in the background. - */ -@protocol GAITracker - -/*! - Name of this tracker. - */ -@property(nonatomic, readonly) NSString *name; - -/*! - Allow collection of IDFA and related fields if set to true. Default is false. - */ -@property(nonatomic) BOOL allowIDFACollection; - -/*! - Set a tracking parameter. - - @param parameterName The parameter name. - - @param value The value to set for the parameter. If this is nil, the - value for the parameter will be cleared. - */ -- (void)set:(NSString *)parameterName - value:(NSString *)value; - -/*! - Get a tracking parameter. - - @param parameterName The parameter name. - - @returns The parameter value, or nil if no value for the given parameter is - set. - */ -- (NSString *)get:(NSString *)parameterName; - -/*! - Queue tracking information with the given parameter values. - - @param parameters A map from parameter names to parameter values which will be - set just for this piece of tracking information, or nil for none. - */ -- (void)send:(NSDictionary *)parameters; - -@end diff --git a/PRODUCTNAME/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement b/PRODUCTNAME/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement new file mode 100755 index 0000000..2561d1a Binary files /dev/null and b/PRODUCTNAME/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement differ diff --git a/PRODUCTNAME/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap b/PRODUCTNAME/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap new file mode 100755 index 0000000..b66fb64 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap @@ -0,0 +1,10 @@ +framework module GoogleAppMeasurement { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m new file mode 100644 index 0000000..abffc3e --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m @@ -0,0 +1,1034 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TargetConditionals.h" + +#if TARGET_OS_IOS || TARGET_OS_TV + +#import +#import +#import +#import "../Common/GULLoggerCodes.h" +#import "Internal/GULAppDelegateSwizzler_Private.h" +#import "Private/GULAppDelegateSwizzler.h" + +#import +#import + +// Implementations need to be typed before calling the implementation directly to cast the +// arguments and the return types correctly. Otherwise, it will crash the app. +typedef BOOL (*GULRealOpenURLSourceApplicationAnnotationIMP)( + id, SEL, UIApplication *, NSURL *, NSString *, id); + +typedef BOOL (*GULRealOpenURLOptionsIMP)( + id, SEL, UIApplication *, NSURL *, NSDictionary *); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)( + id, SEL, UIApplication *, NSString *, void (^)()); +#pragma clang diagnostic pop + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef BOOL (*GULRealContinueUserActivityIMP)( + id, SEL, UIApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects)); +#pragma clang diagnostic pop + +typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, UIApplication *, NSData *); + +typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id, + SEL, + UIApplication *, + NSError *); + +typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, UIApplication *, NSDictionary *); + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +// This is needed to for the library to be warning free on iOS versions < 7. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)( + id, SEL, UIApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)); +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + +typedef void (^GULAppDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; + +static NSString *const kGULAppDelegateKeyPath = @"delegate"; + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/AppDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App Delegate Proxying. */ +static NSString *const kGULFirebaseAppDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App Delegate Proxying. */ +static NSString *const kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the App Delegate. */ +static NSString *const kGULAppDelegatePrefix = @"GUL_"; + +/** The original instance of App Delegate. */ +static id gOriginalAppDelegate; + +/** The original App Delegate class */ +static Class gOriginalAppDelegateClass; + +/** The subclass of the original App Delegate. */ +static Class gAppDelegateSubclass; + +/** Remote notification methods selectors + * + * We have to opt out of referencing APNS related App Delegate methods directly to prevent + * an Apple review warning email about missing Push Notification Entitlement + * (like here: https://github.com/firebase/firebase-ios-sdk/issues/2807). From our experience, the + * warning is triggered when any of the symbols is present in the application sent to review, even + * if the code is never executed. Because GULAppDelegateSwizzler may be used by applications that + * are not using APNS we have to refer to the methods indirectly using selector constructed from + * string. + * + * NOTE: None of the methods is proxied unless it is explicitly requested by calling the method + * +[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods] + */ +static NSString *const kGULDidRegisterForRemoteNotificationsSEL = + @"application:didRegisterForRemoteNotificationsWithDeviceToken:"; +static NSString *const kGULDidFailToRegisterForRemoteNotificationsSEL = + @"application:didFailToRegisterForRemoteNotificationsWithError:"; +static NSString *const kGULDidReceiveRemoteNotificationSEL = + @"application:didReceiveRemoteNotification:"; +static NSString *const kGULDidReceiveRemoteNotificationWithCompletionSEL = + @"application:didReceiveRemoteNotification:fetchCompletionHandler:"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULZeroingWeakContainer +@end + +@interface GULAppDelegateObserver : NSObject +@end + +@implementation GULAppDelegateObserver { + BOOL _isObserving; +} + ++ (GULAppDelegateObserver *)sharedInstance { + static GULAppDelegateObserver *instance; + static dispatch_once_t once; + dispatch_once(&once, ^{ + instance = [[GULAppDelegateObserver alloc] init]; + }); + return instance; +} + +- (void)observeUIApplication { + if (_isObserving) { + return; + } + [[GULAppDelegateSwizzler sharedApplication] + addObserver:self + forKeyPath:kGULAppDelegateKeyPath + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:nil]; + _isObserving = YES; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqual:kGULAppDelegateKeyPath]) { + id newValue = change[NSKeyValueChangeNewKey]; + id oldValue = change[NSKeyValueChangeOldKey]; + if ([newValue isEqual:oldValue]) { + return; + } + // Free the stored app delegate instance because it has been changed to a different instance to + // avoid keeping it alive forever. + if ([oldValue isEqual:gOriginalAppDelegate]) { + gOriginalAppDelegate = nil; + // Remove the observer. Parse it to NSObject to avoid warning. + [[GULAppDelegateSwizzler sharedApplication] removeObserver:self + forKeyPath:kGULAppDelegateKeyPath]; + _isObserving = NO; + } + } +} + +@end + +@implementation GULAppDelegateSwizzler + +static dispatch_once_t sProxyAppDelegateOnceToken; +static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; + +#pragma mark - Public methods + ++ (BOOL)isAppDelegateProxyEnabled { + NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; + + id isFirebaseProxyEnabledPlistValue = infoDictionary[kGULFirebaseAppDelegateProxyEnabledPlistKey]; + id isGoogleProxyEnabledPlistValue = + infoDictionary[kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey]; + + // Enabled by default. + BOOL isFirebaseAppDelegateProxyEnabled = YES; + BOOL isGoogleUtilitiesAppDelegateProxyEnabled = YES; + + if ([isFirebaseProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isFirebaseAppDelegateProxyEnabled = [isFirebaseProxyEnabledPlistValue boolValue]; + } + + if ([isGoogleProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isGoogleUtilitiesAppDelegateProxyEnabled = [isGoogleProxyEnabledPlistValue boolValue]; + } + + // Only deactivate the proxy if it is explicitly disabled by app developers using either one of + // the plist flags. + return isFirebaseAppDelegateProxyEnabled && isGoogleUtilitiesAppDelegateProxyEnabled; +} + ++ (GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor { + NSAssert(interceptor, @"AppDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(UIApplicationDelegate)], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling000], + @"AppDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(UIApplicationDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling001], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = [NSString stringWithFormat:@"%@%p", kGULAppDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling002], + @"AppDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULZeroingWeakContainer *weakObject = [[GULZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULAppDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"AppDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"AppDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling003], + @"AppDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULZeroingWeakContainer *weakContainer = [GULAppDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling004], + @"AppDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + ++ (void)proxyOriginalDelegate { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + dispatch_once(&sProxyAppDelegateOnceToken, ^{ + id originalDelegate = + [GULAppDelegateSwizzler sharedApplication].delegate; + [GULAppDelegateSwizzler proxyAppDelegate:originalDelegate]; + }); +} + ++ (void)proxyOriginalDelegateIncludingAPNSMethods { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + [self proxyOriginalDelegate]; + + dispatch_once(&sProxyAppDelegateRemoteNotificationOnceToken, ^{ + id appDelegate = [GULAppDelegateSwizzler sharedApplication].delegate; + + NSMutableDictionary *realImplementationsBySelector = + [objc_getAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey) mutableCopy]; + + [self proxyRemoteNotificationsMethodsWithAppDelegateSubClass:gAppDelegateSubclass + realClass:gOriginalAppDelegateClass + appDelegate:appDelegate + realImplementationsBySelector:realImplementationsBySelector]; + + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN); + [self reassignAppDelegate]; + }); +} + +#pragma mark - Create proxy + ++ (UIApplication *)sharedApplication { + if ([GULAppEnvironmentUtil isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - Override default methods + +/** Creates a new subclass of the class of the given object and sets the isa value of the given + * object to the new subclass. Additionally this copies methods to that new subclass that allow us + * to intercept UIApplicationDelegate methods. This is better known as isa swizzling. + * + * @param appDelegate The object to which you want to isa swizzle. This has to conform to the + * UIApplicationDelegate subclass. + * @return Returns the new subclass. + */ ++ (nullable Class)createSubclassWithObject:(id)appDelegate { + Class realClass = [appDelegate class]; + + // Create GUL__ + NSString *classNameWithPrefix = + [kGULAppDelegatePrefix stringByAppendingString:NSStringFromClass(realClass)]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling005], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: %@", + NSStringFromClass(realClass), newClassName); + return nil; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class appDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (appDelegateSubClass == Nil) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling006], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: Nil", + NSStringFromClass(realClass)); + return nil; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // Add the following methods from GULAppDelegate class, and store the real implementation so it + // can forward to the real one. + // For application:openURL:options: + SEL applicationOpenURLOptionsSEL = @selector(application:openURL:options:); + if ([appDelegate respondsToSelector:applicationOpenURLOptionsSEL]) { + // Only add the application:openURL:options: method if the original AppDelegate implements it. + // This fixes a bug if an app only implements application:openURL:sourceApplication:annotation: + // (if we add the `options` method, iOS sees that one exists and does not call the + // `sourceApplication` method, which in this case is the only one the app implements). + + [self proxyDestinationSelector:applicationOpenURLOptionsSEL + implementationsFromSourceSelector:applicationOpenURLOptionsSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + + // For application:continueUserActivity:restorationHandler: + SEL continueUserActivitySEL = @selector(application:continueUserActivity:restorationHandler:); + [self proxyDestinationSelector:continueUserActivitySEL + implementationsFromSourceSelector:continueUserActivitySEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:handleEventsForBackgroundURLSession:completionHandler: + SEL handleEventsForBackgroundURLSessionSEL = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + [self proxyDestinationSelector:handleEventsForBackgroundURLSessionSEL + implementationsFromSourceSelector:handleEventsForBackgroundURLSessionSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + +#if TARGET_OS_IOS + // For application:openURL:sourceApplication:annotation: + SEL openURLSourceApplicationAnnotationSEL = @selector(application: + openURL:sourceApplication:annotation:); + + [self proxyDestinationSelector:openURLSourceApplicationAnnotationSEL + implementationsFromSourceSelector:openURLSourceApplicationAnnotationSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS + + // Override the description too so the custom class name will not show up. + [GULAppDelegateSwizzler addInstanceMethodWithDestinationSelector:@selector(description) + withImplementationFromSourceSelector:@selector(fakeDescription) + fromClass:[self class] + toClass:appDelegateSubClass]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(appDelegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(appDelegateSubClass)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling007], + @"Cannot create subclass of App Delegate, because the created subclass is not the " + @"same size. %@", + NSStringFromClass(realClass)); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return nil; + } + + // Make the newly created class to be the subclass of the real App Delegate class. + objc_registerClassPair(appDelegateSubClass); + if (object_setClass(appDelegate, appDelegateSubClass)) { + GULLogDebug(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling008], + @"Successfully created App Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULAppDelegateSwizzler correctAppDelegateProxyKey]); + } + + return appDelegateSubClass; +} + ++ (void)proxyRemoteNotificationsMethodsWithAppDelegateSubClass:(Class)appDelegateSubClass + realClass:(Class)realClass + appDelegate:(id)appDelegate + realImplementationsBySelector: + (NSMutableDictionary *)realImplementationsBySelector { + if (realClass == nil || appDelegateSubClass == nil || appDelegate == nil || + realImplementationsBySelector == nil) { + // The App Delegate has not been swizzled. + return; + } + + // For application:didRegisterForRemoteNotificationsWithDeviceToken: + SEL didRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + SEL didRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didRegisterForRemoteNotificationsWithDeviceToken:); + + [self proxyDestinationSelector:didRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didFailToRegisterForRemoteNotificationsWithError: + SEL didFailToRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + SEL didFailToRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didFailToRegisterForRemoteNotificationsWithError:); + + [self proxyDestinationSelector:didFailToRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didFailToRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification: + SEL didReceiveRemoteNotificationSEL = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + SEL didReceiveRemoteNotificationDonotSEL = @selector(application: + donor_didReceiveRemoteNotification:); + + [self proxyDestinationSelector:didReceiveRemoteNotificationSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationDonotSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification:fetchCompletionHandler: +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + if ([GULAppEnvironmentUtil isIOS7OrHigher]) { + SEL didReceiveRemoteNotificationWithCompletionSEL = + NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + SEL didReceiveRemoteNotificationWithCompletionDonorSEL = + @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); + if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { + // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if + // the original AppDelegate implements it. + // This fixes a bug if an app only implements application:didReceiveRemoteNotification: + // (if we add the method with completion, iOS sees that one exists and does not call + // the method without the completion, which in this case is the only one the app implements). + + [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + } +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +} + +/// We have to do this to invalidate the cache that caches the original respondsToSelector of +/// openURL handlers. Without this, it won't call the default implementations because the system +/// checks and caches them. +/// Register KVO only once. Otherwise, the observing method will be called as many times as +/// being registered. ++ (void)reassignAppDelegate { + id delegate = [self sharedApplication].delegate; + [self sharedApplication].delegate = nil; + [self sharedApplication].delegate = delegate; + gOriginalAppDelegate = delegate; + [[GULAppDelegateObserver sharedInstance] observeUIApplication]; +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULAppDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULAppDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULAppDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULAppDelegateInterceptorCallback)callback { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULAppDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeAppDelegateSwizzling010], + @"AppDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + +// The methods below are donor methods which are added to the dynamic subclass of the App Delegate. +// They are called within the scope of the real App Delegate so |self| does not refer to the +// GULAppDelegateSwizzler instance but the real App Delegate instance. + +#pragma mark - [Donor Methods] Overridden instance description method + +- (NSString *)fakeDescription { + Class realClass = objc_getAssociatedObject(self, &kGULRealClassKey); + return [NSString stringWithFormat:@"<%@: %p>", realClass, self]; +} + +#pragma mark - [Donor Methods] URL overridden handler methods + +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options { + SEL methodSelector = @selector(application:openURL:options:); + // Call the real implementation if the real App Delegate has any. + NSValue *openURLIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLOptionsIMP openURLOptionsIMP = [openURLIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + +// This is needed to for the library to be warning free on iOS versions < 9. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + openURL:url + options:options]; + }]; +#pragma clang diagnostic pop + if (openURLOptionsIMP) { + returnedValue |= openURLOptionsIMP(self, methodSelector, application, url, options); + } + return returnedValue; +} + +#if TARGET_OS_IOS + +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + sourceApplication:(NSString *)sourceApplication + annotation:(id)annotation { + SEL methodSelector = @selector(application:openURL:sourceApplication:annotation:); + + // Call the real implementation if the real App Delegate has any. + NSValue *openURLSourceAppAnnotationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLSourceApplicationAnnotationIMP openURLSourceApplicationAnnotationIMP = + [openURLSourceAppAnnotationIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + returnedValue |= [interceptor application:application + openURL:url + sourceApplication:sourceApplication + annotation:annotation]; +#pragma clang diagnostic pop + }]; + if (openURLSourceApplicationAnnotationIMP) { + returnedValue |= openURLSourceApplicationAnnotationIMP(self, methodSelector, application, url, + sourceApplication, annotation); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS + +#pragma mark - [Donor Methods] Network overridden handler methods + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +- (void)application:(UIApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(void (^)())completionHandler API_AVAILABLE(ios(7.0)) { +#pragma clang diagnostic pop + SEL methodSelector = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + NSValue *handleBackgroundSessionPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealHandleEventsForBackgroundURLSessionIMP handleBackgroundSessionIMP = + [handleBackgroundSessionPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + [interceptor application:application + handleEventsForBackgroundURLSession:identifier + completionHandler:completionHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (handleBackgroundSessionIMP) { + handleBackgroundSessionIMP(self, methodSelector, application, identifier, completionHandler); + } +} + +#pragma mark - [Donor Methods] User Activities overridden handler methods + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (BOOL)application:(UIApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { + SEL methodSelector = @selector(application:continueUserActivity:restorationHandler:); + NSValue *continueUserActivityIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealContinueUserActivityIMP continueUserActivityIMP = + continueUserActivityIMPPointer.pointerValue; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + continueUserActivity:userActivity + restorationHandler:restorationHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (continueUserActivityIMP) { + returnedValue |= continueUserActivityIMP(self, methodSelector, application, userActivity, + restorationHandler); + } + return returnedValue; +} +#pragma clang diagnostic pop + +#pragma mark - [Donor Methods] Remote Notifications + +- (void)application:(UIApplication *)application + donor_didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + SEL methodSelector = NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + + NSValue *didRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidRegisterForRemoteNotificationsIMP didRegisterForRemoteNotificationsIMP = + [didRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&deviceToken) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didRegisterForRemoteNotificationsIMP) { + didRegisterForRemoteNotificationsIMP(self, methodSelector, application, deviceToken); + } +} + +- (void)application:(UIApplication *)application + donor_didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + SEL methodSelector = NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + NSValue *didFailToRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidFailToRegisterForRemoteNotificationsIMP didFailToRegisterForRemoteNotificationsIMP = + [didFailToRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&error) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didFailToRegisterForRemoteNotificationsIMP) { + didFailToRegisterForRemoteNotificationsIMP(self, methodSelector, application, error); + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +// This is needed to for the library to be warning free on iOS versions < 7. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (void)application:(UIApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + NSValue *didReceiveRemoteNotificationWithCompletionIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationWithCompletionIMP + didReceiveRemoteNotificationWithCompletionIMP = + [didReceiveRemoteNotificationWithCompletionIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation setArgument:(void *)(&completionHandler) atIndex:4]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationWithCompletionIMP) { + didReceiveRemoteNotificationWithCompletionIMP(self, methodSelector, application, userInfo, + completionHandler); + } +} +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + +- (void)application:(UIApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + NSValue *didReceiveRemoteNotificationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationIMP didReceiveRemoteNotificationIMP = + [didReceiveRemoteNotificationIMPPointer pointerValue]; + + // Notify interceptors. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation invoke]; + }]; +#pragma clang diagnostic pop + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationIMP) { + didReceiveRemoteNotificationIMP(self, methodSelector, application, userInfo); + } +} + ++ (nullable NSInvocation *)appDelegateInvocationForSelector:(SEL)selector { + struct objc_method_description methodDescription = + protocol_getMethodDescription(@protocol(UIApplicationDelegate), selector, NO, YES); + if (methodDescription.types == NULL) { + return nil; + } + + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + return [NSInvocation invocationWithMethodSignature:signature]; +} + ++ (void)proxyAppDelegate:(id)appDelegate { + if (![appDelegate conformsToProtocol:@protocol(UIApplicationDelegate)]) { + GULLogNotice( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate], + @"App Delegate does not conform to UIApplicationDelegate protocol. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + id originalDelegate = appDelegate; + // Do not create a subclass if it is not enabled. + if (![GULAppDelegateSwizzler isAppDelegateProxyEnabled]) { + GULLogNotice(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling011], + @"App Delegate Proxy is disabled. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + // Do not accept nil delegate. + if (!originalDelegate) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling012], + @"Cannot create App Delegate Proxy because App Delegate instance is nil. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + @try { + gOriginalAppDelegateClass = [originalDelegate class]; + gAppDelegateSubclass = [self createSubclassWithObject:originalDelegate]; + [self reassignAppDelegate]; + } @catch (NSException *exception) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling013], + @"Cannot create App Delegate Proxy. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } +} + +#pragma mark - Methods to print correct debug logs + ++ (NSString *)correctAppDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseAppDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey; +} + ++ (NSString *)correctAlternativeWhenAppDelegateProxyNotCreated { + return NSClassFromString(@"FIRCore") + ? @"To log deep link campaigns manually, call the methods in " + @"FIRAnalytics+AppDelegate.h." + : @""; +} + +#pragma mark - Private Methods for Testing + +#ifdef GUL_APP_DELEGATE_TESTING + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (void)resetProxyOriginalDelegateOnceToken { + sProxyAppDelegateOnceToken = 0; + sProxyAppDelegateRemoteNotificationOnceToken = 0; +} + ++ (id)originalDelegate { + return gOriginalAppDelegate; +} + +#endif // GUL_APP_DELEGATE_TESTING + +@end + +#endif // TARGET_OS_IOS || TARGET_OS_TV diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h new file mode 100644 index 0000000..6e6b556 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class UIApplication; + +NS_ASSUME_NONNULL_BEGIN + +@interface GULAppDelegateSwizzler () + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param appDelegate The object that needs to be isa swizzled. This should conform to the + * UIApplicationDelegate protocol. + */ ++ (void)proxyAppDelegate:(id)appDelegate; + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +#ifdef GUL_APP_DELEGATE_TESTING // Methods only used in tests. + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** Resets the token that prevents the app delegate proxy from being isa swizzled multiple times. */ ++ (void)resetProxyOriginalDelegateOnceToken; + +/** Returns the original app delegate that was proxied. + * + * @return The original app delegate instance that was proxied. + */ ++ (id)originalDelegate; + +#endif // GUL_APP_DELEGATE_TESTING + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h new file mode 100644 index 0000000..d861ed1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class UIApplication; +@protocol UIApplicationDelegate; + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULAppDelegateInterceptorID; + +/** This class contains methods that isa swizzle the app delegate. */ +@interface GULAppDelegateSwizzler : NSProxy + +/** Registers an app delegate interceptor whose methods will be invoked as they're invoked on the + * original app delegate. + * + * @param interceptor An instance of a class that conforms to the UIApplicationDelegate protocol. + * The interceptor is NOT retained. + * @return A unique GULAppDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor; + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID; + +/** This method ensures that the original app delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the app delegate once). + * + * This method doesn't proxy APNS related methods: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * To proxy these methods use +[GULAppDelegateSwizzler + * proxyOriginalDelegateIncludingAPNSMethods]. The methods have to be proxied separately to + * avoid potential warnings from Apple review about missing Push Notification Entitlement (e.g. + * https://github.com/firebase/firebase-ios-sdk/issues/2807) + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegateIncludingAPNSMethods + */ ++ (void)proxyOriginalDelegate; + +/** This method ensures that the original app delegate has been proxied including APNS related + * methods. Call this before registering your interceptor. This method is safe to call multiple + * times (but it only proxies the app delegate once) or + * after +[GULAppDelegateSwizzler proxyOriginalDelegate] + * + * This method calls +[GULAppDelegateSwizzler proxyOriginalDelegate] under the hood. + * After calling this method the following App Delegate methods will be proxied in addition to + * the methods proxied by proxyOriginalDelegate: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegate + */ ++ (void)proxyOriginalDelegateIncludingAPNSMethods; + +/** Indicates whether app delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if AppDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isAppDelegateProxyEnabled; + +/** Returns the current sharedApplication. + * + * @return the current UIApplication if in an app, or nil if in extension or if it doesn't exist. + */ ++ (nullable UIApplication *)sharedApplication; + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h new file mode 100644 index 0000000..fd22ba6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +typedef NS_ENUM(NSInteger, GULSwizzlerMessageCode) { + // App Delegate Swizzling. + kGULSwizzlerMessageCodeAppDelegateSwizzling000 = 1000, // I-SWZ001000 + kGULSwizzlerMessageCodeAppDelegateSwizzling001 = 1001, // I-SWZ001001 + kGULSwizzlerMessageCodeAppDelegateSwizzling002 = 1002, // I-SWZ001002 + kGULSwizzlerMessageCodeAppDelegateSwizzling003 = 1003, // I-SWZ001003 + kGULSwizzlerMessageCodeAppDelegateSwizzling004 = 1004, // I-SWZ001004 + kGULSwizzlerMessageCodeAppDelegateSwizzling005 = 1005, // I-SWZ001005 + kGULSwizzlerMessageCodeAppDelegateSwizzling006 = 1006, // I-SWZ001006 + kGULSwizzlerMessageCodeAppDelegateSwizzling007 = 1007, // I-SWZ001007 + kGULSwizzlerMessageCodeAppDelegateSwizzling008 = 1008, // I-SWZ001008 + kGULSwizzlerMessageCodeAppDelegateSwizzling009 = 1009, // I-SWZ001009 + kGULSwizzlerMessageCodeAppDelegateSwizzling010 = 1010, // I-SWZ001010 + kGULSwizzlerMessageCodeAppDelegateSwizzling011 = 1011, // I-SWZ001011 + kGULSwizzlerMessageCodeAppDelegateSwizzling012 = 1012, // I-SWZ001012 + kGULSwizzlerMessageCodeAppDelegateSwizzling013 = 1013, // I-SWZ001013 + kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate = 1014, // I-SWZ001014 + + // Method Swizzling. + kGULSwizzlerMessageCodeMethodSwizzling000 = 2000, // I-SWZ002000 +}; diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h new file mode 100644 index 0000000..d550264 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GULAppEnvironmentUtil : NSObject + +/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, +/// development environment or sideloaded. ++ (BOOL)isFromAppStore; + +/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. +/// Returns NO otherwise. ++ (BOOL)isAppStoreReceiptSandbox; + +/// Indicates whether the app is on simulator or not at runtime depending on the device +/// architecture. ++ (BOOL)isSimulator; + +/// The current device model. Returns an empty string if device model cannot be retrieved. ++ (NSString *)deviceModel; + +/// The current operating system version. Returns an empty string if the system version cannot be +/// retrieved. ++ (NSString *)systemVersion; + +/// Indicates whether it is running inside an extension or an app. ++ (BOOL)isAppExtension; + +/// @return Returns @YES when is run on iOS version greater or equal to 7.0 ++ (BOOL)isIOS7OrHigher; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m new file mode 100644 index 0000000..8327438 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m @@ -0,0 +1,262 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GULAppEnvironmentUtil.h" + +#import +#import +#import +#import + +#if TARGET_OS_IOS +#import +#endif + +/// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from +/// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just +/// provide the definitions here. +#if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO) +#define LC_ENCRYPTION_INFO 0x21 +struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; +}; +#endif + +@implementation GULAppEnvironmentUtil + +/// A key for the Info.plist to enable or disable checking if the App Store is running in a sandbox. +/// This will affect your data integrity when using Firebase Analytics, as it will disable some +/// necessary checks. +static NSString *const kFIRAppStoreReceiptURLCheckEnabledKey = + @"FirebaseAppStoreReceiptURLCheckEnabled"; + +/// The file name of the sandbox receipt. This is available on iOS >= 8.0 +static NSString *const kFIRAIdentitySandboxReceiptFileName = @"sandboxReceipt"; + +/// The following copyright from Landon J. Fuller applies to the isAppEncrypted function. +/// +/// Copyright (c) 2017 Landon J. Fuller +/// All rights reserved. +/// +/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +/// and associated documentation files (the "Software"), to deal in the Software without +/// restriction, including without limitation the rights to use, copy, modify, merge, publish, +/// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +/// Software is furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in all copies or +/// substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +/// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +/// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/// +/// Comment from iPhone Dev Wiki +/// Crack Prevention: +/// App Store binaries are signed by both their developer and Apple. This encrypts the binary so +/// that decryption keys are needed in order to make the binary readable. When iOS executes the +/// binary, the decryption keys are used to decrypt the binary into a readable state where it is +/// then loaded into memory and executed. iOS can tell the encryption status of a binary via the +/// cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is a non-zero +/// value then the binary is encrypted. +/// +/// 'Cracking' works by letting the kernel decrypt the binary then siphoning the decrypted data into +/// a new binary file, resigning, and repackaging. This will only work on jailbroken devices as +/// codesignature validation has been removed. Resigning takes place because while the codesignature +/// doesn't have to be valid thanks to the jailbreak, it does have to be in place unless you have +/// AppSync or similar to disable codesignature checks. +/// +/// More information at Landon Fuller's blog +static BOOL IsAppEncrypted() { + const struct mach_header *executableHeader = NULL; + for (uint32_t i = 0; i < _dyld_image_count(); i++) { + const struct mach_header *header = _dyld_get_image_header(i); + if (header && header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + + if (!executableHeader) { + return NO; + } + + BOOL is64bit = (executableHeader->magic == MH_MAGIC_64); + uintptr_t cursor = (uintptr_t)executableHeader + + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header)); + const struct segment_command *segmentCommand = NULL; + uint32_t i = 0; + + while (i++ < executableHeader->ncmds) { + segmentCommand = (struct segment_command *)cursor; + + if (!segmentCommand) { + continue; + } + + if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) || + (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) { + if (is64bit) { + struct encryption_info_command_64 *cryptCmd = + (struct encryption_info_command_64 *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } else { + struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } + } + cursor += segmentCommand->cmdsize; + } + + return NO; +} + +static BOOL HasSCInfoFolder() { +#if TARGET_OS_IOS || TARGET_OS_TV + NSString *bundlePath = [NSBundle mainBundle].bundlePath; + NSString *scInfoPath = [bundlePath stringByAppendingPathComponent:@"SC_Info"]; + return [[NSFileManager defaultManager] fileExistsAtPath:scInfoPath]; +#elif TARGET_OS_OSX + return NO; +#endif +} + +static BOOL HasEmbeddedMobileProvision() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"].length > 0; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isFromAppStore { + static dispatch_once_t isEncryptedOnce; + static BOOL isEncrypted = NO; + + dispatch_once(&isEncryptedOnce, ^{ + isEncrypted = IsAppEncrypted(); + }); + + if ([GULAppEnvironmentUtil isSimulator]) { + return NO; + } + + // If an app contain the sandboxReceipt file, it means its coming from TestFlight + // This must be checked before the SCInfo Folder check below since TestFlight apps may + // also have an SCInfo folder. + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox]) { + return NO; + } + + if (HasSCInfoFolder()) { + // When iTunes downloads a .ipa, it also gets a customized .sinf file which is added to the + // main SC_Info directory. + return YES; + } + + // For iOS >= 8.0, iTunesMetadata.plist is moved outside of the sandbox. Any attempt to read + // the iTunesMetadata.plist outside of the sandbox will be rejected by Apple. + // If the app does not contain the embedded.mobileprovision which is stripped out by Apple when + // the app is submitted to store, then it is highly likely that it is from Apple Store. + return isEncrypted && !HasEmbeddedMobileProvision(); +} + ++ (BOOL)isAppStoreReceiptSandbox { + // Since checking the App Store's receipt URL can be memory intensive, check the option in the + // Info.plist if developers opted out of this check. + id enableSandboxCheck = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRAppStoreReceiptURLCheckEnabledKey]; + if (enableSandboxCheck && [enableSandboxCheck isKindOfClass:[NSNumber class]] && + ![enableSandboxCheck boolValue]) { + return NO; + } +// The #else is for pre Xcode 9 where @available is not yet implemented. +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; + NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; + return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; + } + return NO; +} + ++ (BOOL)isSimulator { +#if TARGET_OS_IOS || TARGET_OS_TV + NSString *platform = [GULAppEnvironmentUtil deviceModel]; + return [platform isEqual:@"x86_64"] || [platform isEqual:@"i386"]; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (NSString *)deviceModel { + static dispatch_once_t once; + static NSString *deviceModel; + + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + deviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return deviceModel; +} + ++ (NSString *)systemVersion { +#if TARGET_OS_IOS + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_TV + // Assemble the systemVersion, excluding the patch version if it's 0. + NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; + NSMutableString *versionString = [[NSMutableString alloc] + initWithFormat:@"%ld.%ld", (long)osVersion.majorVersion, (long)osVersion.minorVersion]; + if (osVersion.patchVersion != 0) { + [versionString appendFormat:@".%ld", (long)osVersion.patchVersion]; + } + return versionString; +#endif +} + ++ (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV + // Documented by Apple + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isIOS7OrHigher { +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + return YES; + } + + return NO; +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m new file mode 100644 index 0000000..495e583 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m @@ -0,0 +1,209 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULLogger.h" + +#include + +#import +#import "Public/GULLoggerLevel.h" + +/// ASL client facility name used by GULLogger. +const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; + +static dispatch_once_t sGULLoggerOnceToken; + +static aslclient sGULLoggerClient; + +static dispatch_queue_t sGULClientQueue; + +static BOOL sGULLoggerDebugMode; + +static GULLoggerLevel sGULLoggerMaximumLevel; + +// Allow clients to register a version to include in the log. +static const char *sVersion = ""; + +static GULLoggerService kGULLoggerLogger = @"[GULLogger]"; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void GULLoggerInitializeASL(void) { + dispatch_once(&sGULLoggerOnceToken, ^{ + NSInteger majorOSVersion = [[GULAppEnvironmentUtil systemVersion] integerValue]; + uint32_t aslOptions = ASL_OPT_STDERR; +#if TARGET_OS_SIMULATOR + // The iOS 11 simulator doesn't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 11) { + aslOptions = 0; + } +#else + // Devices running iOS 10 or higher don't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 10) { + aslOptions = 0; + } +#endif // TARGET_OS_SIMULATOR + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // asl is deprecated + // Initialize the ASL client handle. + sGULLoggerClient = asl_open(NULL, kGULLoggerASLClientFacilityName, aslOptions); + sGULLoggerMaximumLevel = GULLoggerLevelNotice; + + // Set the filter used by system/device log. Initialize in default mode. + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE)); + + sGULClientQueue = dispatch_queue_create("GULLoggingClientQueue", DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(sGULClientQueue, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); +#ifdef DEBUG + sMessageCodeRegex = [NSRegularExpression regularExpressionWithPattern:kMessageCodePattern + options:0 + error:NULL]; +#endif + }); +} + +void GULLoggerEnableSTDERR(void) { + asl_add_log_file(sGULLoggerClient, STDERR_FILENO); +} + +void GULLoggerForceDebug(void) { + // We should enable debug mode if we're not running from App Store. + if (![GULAppEnvironmentUtil isFromAppStore]) { + sGULLoggerDebugMode = YES; + GULSetLoggerLevel(GULLoggerLevelDebug); + } +} + +__attribute__((no_sanitize("thread"))) void GULSetLoggerLevel(GULLoggerLevel loggerLevel) { + if (loggerLevel < GULLoggerLevelMin || loggerLevel > GULLoggerLevelMax) { + GULLogError(kGULLoggerLogger, NO, @"I-COR000023", @"Invalid logger level, %ld", + (long)loggerLevel); + return; + } + GULLoggerInitializeASL(); + // We should not raise the logger level if we are running from App Store. + if (loggerLevel >= GULLoggerLevelNotice && [GULAppEnvironmentUtil isFromAppStore]) { + return; + } + + sGULLoggerMaximumLevel = loggerLevel; + dispatch_async(sGULClientQueue, ^{ + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(loggerLevel)); + }); +} + +/** + * Check if the level is high enough to be loggable. + */ +__attribute__((no_sanitize("thread"))) BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel) { + GULLoggerInitializeASL(); + if (sGULLoggerDebugMode) { + return YES; + } + return (BOOL)(loggerLevel <= sGULLoggerMaximumLevel); +} + +#ifdef DEBUG +void GULResetLogger() { + sGULLoggerOnceToken = 0; +} + +aslclient getGULLoggerClient() { + return sGULLoggerClient; +} + +dispatch_queue_t getGULClientQueue() { + return sGULClientQueue; +} + +BOOL getGULLoggerDebugMode() { + return sGULLoggerDebugMode; +} +#endif + +void GULLoggerRegisterVersion(const char *version) { + sVersion = version; +} + +void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + GULLoggerInitializeASL(); + if (!(level <= sGULLoggerMaximumLevel || sGULLoggerDebugMode || forceLog)) { + return; + } + +#ifdef DEBUG + NSCAssert(messageCode.length == 11, @"Incorrect message code length."); + NSRange messageCodeRange = NSMakeRange(0, messageCode.length); + NSUInteger numberOfMatches = [sMessageCodeRegex numberOfMatchesInString:messageCode + options:0 + range:messageCodeRange]; + NSCAssert(numberOfMatches == 1, @"Incorrect message code format."); +#endif + NSString *logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr]; + logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg]; + dispatch_async(sGULClientQueue, ^{ + asl_log(sGULLoggerClient, NULL, level, "%s", logMsg.UTF8String); + }); +} +#pragma clang diagnostic pop + +/** + * Generates the logging functions using macros. + * + * Calling GULLogError(kGULLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-COR000001] Configure blah failed. + * Calling GULLogDebug(kGULLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-COR000001] Configure succeed. + */ +#define GUL_LOGGING_FUNCTION(level) \ + void GULLog##level(GULLoggerService service, BOOL force, NSString *messageCode, \ + NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + GULLogBasic(GULLoggerLevel##level, service, force, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +GUL_LOGGING_FUNCTION(Error) +GUL_LOGGING_FUNCTION(Warning) +GUL_LOGGING_FUNCTION(Notice) +GUL_LOGGING_FUNCTION(Info) +GUL_LOGGING_FUNCTION(Debug) + +#undef GUL_MAKE_LOGGER + +#pragma mark - GULLoggerWrapper + +@implementation GULLoggerWrapper + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + GULLogBasic(level, service, NO, messageCode, message, args); +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h new file mode 100644 index 0000000..ff42576 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The services used in the logger. + */ +typedef NSString *const GULLoggerService; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initialize GULLogger. + */ +extern void GULLoggerInitializeASL(void); + +/** + * Override log level to Debug. + */ +void GULLoggerForceDebug(void); + +/** + * Turn on logging to STDERR. + */ +extern void GULLoggerEnableSTDERR(void); + +/** + * Changes the default logging level of GULLoggerLevelNotice to a user-specified level. + * The default level cannot be set above GULLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern void GULSetLoggerLevel(GULLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel); + +/** + * Register version to include in logs. + * (required) version + */ +extern void GULLoggerRegisterVersion(const char *version); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type GULLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * GULLogError(kGULLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void GULLogError(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogWarning(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogNotice(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogInfo(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogDebug(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface GULLoggerWrapper : NSObject + +/** + * Objective-C wrapper for GULLogBasic to allow weak linking to GULLogger + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h new file mode 100644 index 0000000..81ff212 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, GULLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + GULLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + GULLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + GULLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + GULLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + GULLoggerLevelDebug = 7, + /** Minimum log level. */ + GULLoggerLevelMin = GULLoggerLevelError, + /** Maximum log level. */ + GULLoggerLevelMax = GULLoggerLevelDebug +} NS_SWIFT_NAME(GoogleLoggerLevel); diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m new file mode 100644 index 0000000..e58df96 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m @@ -0,0 +1,185 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULSwizzler.h" + +#import + +#import +#import "../Common/GULLoggerCodes.h" + +#ifdef GUL_UNSWIZZLING_ENABLED +#import +// We need a private method for an assert. +#import +#endif + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilites/MethodSwizzler]"; + +dispatch_queue_t GetGULSwizzlingQueue() { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.GULSwizzler", DISPATCH_QUEUE_SERIAL); + }); + return queue; +} + +@implementation GULSwizzler + ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block { + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + Class resolvedClass = aClass; + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + resolvedClass = object_getClass(aClass); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"You're attempting to swizzle a method that doesn't exist. (%@, %@)", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + IMP newImp = imp_implementationWithBlock(block); + +#ifdef GUL_UNSWIZZLING_ENABLED + IMP currentImp = class_getMethodImplementation(resolvedClass, selector); + [[GULSwizzlingCache sharedInstance] cacheCurrentIMP:currentImp + forNewIMP:newImp + forClass:resolvedClass + withSelector:selector]; +#endif + + const char *typeEncoding = method_getTypeEncoding(method); + __unused IMP originalImpOfClass = + class_replaceMethod(resolvedClass, selector, newImp, typeEncoding); + +#ifdef GUL_UNSWIZZLING_ENABLED + // If !originalImpOfClass, then the IMP came from a superclass. + if (originalImpOfClass) { + if (originalImpOfClass != + [[GULSwizzlingCache sharedInstance] originalIMPOfCurrentIMP:currentImp]) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeMethodSwizzling000], + @"Swizzling class: %@ SEL:%@ after it has been previously been swizzled.", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + } + } +#endif + }); +} + ++ (void)unswizzleClass:(Class)aClass selector:(SEL)selector isClassSelector:(BOOL)isClassSelector { +#ifdef GUL_UNSWIZZLING_ENABLED + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(aClass != nil && selector != nil, @"You cannot unswizzle a nil class or selector."); + Method method = nil; + Class resolvedClass = aClass; + if (isClassSelector) { + resolvedClass = object_getClass(aClass); + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"Couldn't find the method you're unswizzling in the runtime."); + IMP originalImp = [[GULSwizzlingCache sharedInstance] cachedIMPForClass:resolvedClass + withSelector:selector]; + NSAssert(originalImp, @"This class/selector combination hasn't been swizzled"); + IMP currentImp = method_setImplementation(method, originalImp); + BOOL didRemoveBlock = imp_removeBlock(currentImp); + NSAssert(didRemoveBlock, @"Wasn't able to remove the block of a swizzled IMP."); + [[GULSwizzlingCache sharedInstance] clearCacheForSwizzledIMP:currentImp + selector:selector + aClass:resolvedClass]; + }); +#else + NSAssert(NO, @"Unswizzling is disabled."); +#endif +} + ++ (nullable IMP)originalImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { +#ifdef GUL_UNSWIZZLING_ENABLED + __block IMP originalImp = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Class resolvedClass = isClassSelector ? object_getClass(aClass) : aClass; + originalImp = [[GULSwizzlingCache sharedInstance] cachedIMPForClass:resolvedClass + withSelector:selector]; + NSAssert(originalImp, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + }); + return originalImp; +#else + NSAssert(NO, @"Unswizzling is disabled and the original IMP is not cached."); + return nil; +#endif +} + ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + if (selector == NULL || aClass == nil) { + return nil; + } + __block IMP currentIMP = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"The Method for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + if (method == nil) { + return; + } + currentIMP = method_getImplementation(method); + NSAssert(currentIMP, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + }); + return currentIMP; +} + ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector { + Method method = isClassSelector ? class_getClassMethod(aClass, selector) + : class_getInstanceMethod(aClass, selector); + return method != nil; +} + ++ (NSArray *)ivarObjectsForObject:(id)object { + NSMutableArray *array = [NSMutableArray array]; + unsigned int count; + Ivar *vars = class_copyIvarList([object class], &count); + for (NSUInteger i = 0; i < count; i++) { + const char *typeEncoding = ivar_getTypeEncoding(vars[i]); + // Check to see if the ivar is an object. + if (strncmp(typeEncoding, "@", 1) == 0) { + id ivarObject = object_getIvar(object, vars[i]); + [array addObject:ivarObject]; + } + } + free(vars); + return array; +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h new file mode 100644 index 0000000..a33262a --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h @@ -0,0 +1,207 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * GULOriginalIMPConvenienceMacros.h + * + * This header contains convenience macros for invoking the original IMP of a swizzled method. + */ + +/** + * Invokes original IMP when the original selector takes no arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + */ +#define GUL_INVOKE_ORIGINAL_IMP0(__receivingObject, __swizzledSEL, __returnType, __originalIMP) \ + ((__returnType(*)(id, SEL))__originalIMP)(__receivingObject, __swizzledSEL) + +/** + * Invokes original IMP when the original selector takes 1 argument. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP1(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1)))__originalIMP)(__receivingObject, __swizzledSEL, \ + __arg1) + +/** + * Invokes original IMP when the original selector takes 2 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP2(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2) + +/** + * Invokes original IMP when the original selector takes 3 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP3(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), \ + __typeof__(__arg3)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3) + +/** + * Invokes original IMP when the original selector takes 4 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP4(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3, __arg4) + +/** + * Invokes original IMP when the original selector takes 5 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP5(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5) + +/** + * Invokes original IMP when the original selector takes 6 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP6(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) + +/** + * Invokes original IMP when the original selector takes 7 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP7(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) + +/** + * Invokes original IMP when the original selector takes 8 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP8(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8) + +/** + * Invokes original IMP when the original selector takes 9 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + * @param __arg9 The ninth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP9(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8, \ + __arg9) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8), __typeof__(__arg9)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8, __arg9) diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h new file mode 100644 index 0000000..ab008ca --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class handles the runtime manipulation necessary to instrument selectors. It stores the + * classes and selectors that have been swizzled, and runs all operations on its own queue. + */ +@interface GULSwizzler : NSObject + +/** Manipulates the Objective-C runtime to replace the original IMP with the supplied block. + * + * @param aClass The class to swizzle. + * @param selector The selector of the class to swizzle. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @param block The block that replaces the original IMP. + */ ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block; + +/** Restores the original implementation. + * + * @param aClass The class to unswizzle. + * @param selector The selector to restore the original implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + */ ++ (void)unswizzleClass:(Class)aClass selector:(SEL)selector isClassSelector:(BOOL)isClassSelector; + +/** Returns the current IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime. + */ ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Returns the original IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime before any consumer or GULSwizzler + * swizzled. + */ ++ (nullable IMP)originalImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Checks the runtime to see if a selector exists on a class. If a property is declared as + * @dynamic, we have a reverse swizzling situation, where the implementation of a method exists + * only in concrete subclasses, and NOT in the superclass. We can detect that situation using + * this helper method. Similarly, we can detect situations where a class doesn't implement a + * protocol method. + * + * @param selector The selector to check for. + * @param aClass The class to check. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return YES if the method was found in this selector/class combination, NO otherwise. + */ ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector; + +/** Returns a list of all Objective-C (and not primitive) ivars contained by the given object. + * + * @param object The object whose ivars will be iterated. + * @return The list of ivar objects. + */ ++ (NSArray *)ivarObjectsForObject:(id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h new file mode 100644 index 0000000..36f94a7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h @@ -0,0 +1,49 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework. + +// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given +// such data. To handle data of that size you really should be streaming it rather then doing it all +// in memory. + +@interface NSData (GULGzip) + +/// Returns an data as the result of decompressing the payload of |data|.The data to decompress must +/// be a gzipped payloads. ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error; + +/// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default +/// compression level. ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error; + +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain; +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber +FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber + +typedef NS_ENUM(NSInteger, GULNSDataZlibError) { + GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024, + // An internal zlib error. + // GULNSDataZlibErrorKey will contain the error value. + // NSLocalizedDescriptionKey may contain an error string from zlib. + // Look in zlib.h for list of errors. + GULNSDataZlibErrorInternal, + // There was left over data in the buffer that was not used. + // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes. + GULNSDataZlibErrorDataRemaining +}; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m new file mode 100644 index 0000000..cd3394a --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m @@ -0,0 +1,207 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GULNSData+zlib.h" + +#import + +#define kChunkSize 1024 +#define Z_DEFAULT_COMPRESSION (-1) + +NSString *const GULNSDataZlibErrorDomain = @"com.google.GULNSDataZlibErrorDomain"; +NSString *const GULNSDataZlibErrorKey = @"GULNSDataZlibErrorKey"; +NSString *const GULNSDataZlibRemainingBytesKey = @"GULNSDataZlibRemainingBytesKey"; + +@implementation NSData (GULGzip) + ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + int windowBits = 15; // 15 to enable any window size + windowBits += 32; // and +32 to enable zlib or gzip header detection. + + int retCode; + if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 4x the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length * 4)]; + unsigned char output[kChunkSize]; + + // Loop to collect the data. + do { + // Update what we're passing in. + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = inflate(&strm, Z_NO_FLUSH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + if (strm.msg) { + NSString *message = [NSString stringWithUTF8String:strm.msg]; + if (message) { + [userInfo setObject:message forKey:NSLocalizedDescriptionKey]; + } + } + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + inflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // Make sure there wasn't more data tacked onto the end of a valid compressed stream. + if (strm.avail_in != 0) { + if (error) { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in] + forKey:GULNSDataZlibRemainingBytesKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorDataRemaining + userInfo:userInfo]; + } + result = nil; + } + // The only way out of the loop was by hitting the end of the stream. + NSAssert(retCode == Z_STREAM_END, + @"Thought we finished inflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + inflateEnd(&strm); + + return result; +} + ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + if (error) { + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorGreaterThan32BitsToCompress + userInfo:nil]; + } + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m new file mode 100644 index 0000000..d281eb4 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m @@ -0,0 +1,97 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULMutableDictionary.h" + +@implementation GULMutableDictionary { + /// The mutable dictionary. + NSMutableDictionary *_objects; + + /// Serial synchronization queue. All reads should use dispatch_sync, while writes use + /// dispatch_async. + dispatch_queue_t _queue; +} + +- (instancetype)init { + self = [super init]; + + if (self) { + _objects = [[NSMutableDictionary alloc] init]; + _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (NSString *)description { + __block NSString *description; + dispatch_sync(_queue, ^{ + description = self->_objects.description; + }); + return description; +} + +- (id)objectForKey:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = self->_objects[key]; + }); + return object; +} + +- (void)setObject:(id)object forKey:(id)key { + dispatch_async(_queue, ^{ + self->_objects[key] = object; + }); +} + +- (void)removeObjectForKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_async(_queue, ^{ + [self->_objects removeAllObjects]; + }); +} + +- (NSUInteger)count { + __block NSUInteger count; + dispatch_sync(_queue, ^{ + count = self->_objects.count; + }); + return count; +} + +- (id)objectForKeyedSubscript:(id)key { + // The method this calls is already synchronized. + return [self objectForKey:key]; +} + +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + // The method this calls is already synchronized. + [self setObject:obj forKey:key]; +} + +- (NSDictionary *)dictionary { + __block NSDictionary *dictionary; + dispatch_sync(_queue, ^{ + dictionary = [self->_objects copy]; + }); + return dictionary; +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m new file mode 100644 index 0000000..c322727 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m @@ -0,0 +1,389 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULNetwork.h" +#import "Private/GULNetworkMessageCode.h" + +#import +#import +#import +#import "Private/GULMutableDictionary.h" +#import "Private/GULNetworkConstants.h" + +/// Constant string for request header Content-Encoding. +static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; + +/// Constant string for request header Content-Encoding value. +static NSString *const kGULNetworkContentCompressionValue = @"gzip"; + +/// Constant string for request header Content-Length. +static NSString *const kGULNetworkContentLengthKey = @"Content-Length"; + +/// Constant string for request header Content-Type. +static NSString *const kGULNetworkContentTypeKey = @"Content-Type"; + +/// Constant string for request header Content-Type value. +static NSString *const kGULNetworkContentTypeValue = @"application/x-www-form-urlencoded"; + +/// Constant string for GET request method. +static NSString *const kGULNetworkGETRequestMethod = @"GET"; + +/// Constant string for POST request method. +static NSString *const kGULNetworkPOSTRequestMethod = @"POST"; + +/// Default constant string as a prefix for network logger. +static NSString *const kGULNetworkLogTag = @"Google/Utilities/Network"; + +@interface GULNetwork () +@end + +@implementation GULNetwork { + /// Network reachability. + GULReachabilityChecker *_reachability; + + /// The dictionary of requests by session IDs { NSString : id }. + GULMutableDictionary *_requests; +} + +- (instancetype)init { + return [self initWithReachabilityHost:kGULNetworkReachabilityHost]; +} + +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { + self = [super init]; + if (self) { + // Setup reachability. + _reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:reachabilityHost]; + if (![_reachability start]) { + return nil; + } + + _requests = [[GULMutableDictionary alloc] init]; + _timeoutInterval = kGULNetworkTimeOutInterval; + } + return self; +} + +- (void)dealloc { + _reachability.reachabilityDelegate = nil; + [_reachability stop]; +} + +#pragma mark - External Methods + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler { + [GULNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID + completionHandler:completionHandler]; +} + +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + NSError *compressError = nil; + NSData *compressedData = [NSData gul_dataByGzippingData:payload error:&compressError]; + if (!compressedData || compressError) { + if (compressError || payload.length > 0) { + // If the payload is not empty but it fails to compress the payload, something has been wrong. + [self handleErrorWithCode:GULErrorCodeNetworkPayloadCompression + queue:queue + withHandler:handler]; + return nil; + } + compressedData = [[NSData alloc] init]; + } + + NSString *postLength = @(compressedData.length).stringValue; + + // Set up the request with the compressed data. + [request setValue:postLength forHTTPHeaderField:kGULNetworkContentLengthKey]; + request.HTTPBody = compressedData; + request.HTTPMethod = kGULNetworkPOSTRequestMethod; + [request setValue:kGULNetworkContentTypeValue forHTTPHeaderField:kGULNetworkContentTypeKey]; + [request setValue:kGULNetworkContentCompressionValue + forHTTPHeaderField:kGULNetworkContentCompressionKey]; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncPOSTRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, + NSString *sessionID, NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork000 + message:@"Uploading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + request.HTTPMethod = kGULNetworkGETRequestMethod; + request.allHTTPHeaderFields = headers; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncGETRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, + NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork001 + message:@"Downloading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (BOOL)hasUploadInProgress { + return _requests.count > 0; +} + +#pragma mark - Network Reachability + +/// Tells reachability delegate to call reachabilityDidChangeToStatus: to notify the network +/// reachability has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + _networkConnected = (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); + [_reachabilityDelegate reachabilityDidChange]; +} + +#pragma mark - Network logger delegate + +- (void)setLoggerDelegate:(id)loggerDelegate { + // Explicitly check whether the delegate responds to the methods because conformsToProtocol does + // not work correctly even though the delegate does respond to the methods. + if (!loggerDelegate || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:contexts:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:context:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:)]) { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork002], + @"Cannot set the network logger delegate: delegate does not conform to the network " + "logger protocol."); + return; + } + _loggerDelegate = loggerDelegate; +} + +#pragma mark - Private methods + +/// Handles network error and calls completion handler with the error. +- (void)handleErrorWithCode:(NSInteger)code + queue:(dispatch_queue_t)queue + withHandler:(GULNetworkCompletionHandler)handler { + NSDictionary *userInfo = @{kGULNetworkErrorContext : @"Failed to create network request"}; + NSError *error = [[NSError alloc] initWithDomain:kGULNetworkErrorDomain + code:code + userInfo:userInfo]; + [self GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeNetwork002 + message:@"Failed to create network request. Code, error" + contexts:@[ @(code), error ]]; + if (handler) { + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + handler(nil, nil, error); + }); + } +} + +#pragma mark - Network logger + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts { + // Let the delegate log the message if there is a valid logger delegate. Otherwise, just log + // errors/warnings/info messages to the console log. + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + contexts:contexts]; + return; + } + if (_isDebugModeEnabled || logLevel == kGULNetworkLogLevelError || + logLevel == kGULNetworkLogLevelWarning || logLevel == kGULNetworkLogLevelInfo) { + NSString *formattedMessage = GULStringWithLogMessage(message, logLevel, contexts); + NSLog(@"%@", formattedMessage); + GULLogBasic((GULLoggerLevel)logLevel, kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, + NULL); + } +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + context:context]; + return; + } + NSArray *contexts = context ? @[ context ] : @[]; + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; + return; + } + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; +} + +/// Returns a string for the given log level (e.g. kGULNetworkLogLevelError -> @"ERROR"). +static NSString *GULLogLevelDescriptionFromLogLevel(GULNetworkLogLevel logLevel) { + static NSDictionary *levelNames = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + levelNames = @{ + @(kGULNetworkLogLevelError) : @"ERROR", + @(kGULNetworkLogLevelWarning) : @"WARNING", + @(kGULNetworkLogLevelInfo) : @"INFO", + @(kGULNetworkLogLevelDebug) : @"DEBUG" + }; + }); + return levelNames[@(logLevel)]; +} + +/// Returns a formatted string to be used for console logging. +static NSString *GULStringWithLogMessage(NSString *message, + GULNetworkLogLevel logLevel, + NSArray *contexts) { + if (!message) { + message = @"(Message was nil)"; + } else if (!message.length) { + message = @"(Message was empty)"; + } + NSMutableString *result = [[NSMutableString alloc] + initWithFormat:@"<%@/%@> %@", kGULNetworkLogTag, GULLogLevelDescriptionFromLogLevel(logLevel), + message]; + + if (!contexts.count) { + return result; + } + + NSMutableArray *formattedContexts = [[NSMutableArray alloc] init]; + for (id item in contexts) { + [formattedContexts addObject:(item != [NSNull null] ? item : @"(nil)")]; + } + + [result appendString:@": "]; + [result appendString:[formattedContexts componentsJoinedByString:@", "]]; + return result; +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m new file mode 100644 index 0000000..90bd03d --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m @@ -0,0 +1,40 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULNetworkConstants.h" + +#import + +NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload"; +NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network"; +NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory"; +const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour +const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute. +NSString *const kGULNetworkReachabilityHost = @"app-measurement.com"; +NSString *const kGULNetworkErrorContext = @"Context"; + +const int kGULNetworkHTTPStatusOK = 200; +const int kGULNetworkHTTPStatusNoContent = 204; +const int kGULNetworkHTTPStatusCodeMultipleChoices = 300; +const int kGULNetworkHTTPStatusCodeMovedPermanently = 301; +const int kGULNetworkHTTPStatusCodeFound = 302; +const int kGULNetworkHTTPStatusCodeNotModified = 304; +const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307; +const int kGULNetworkHTTPStatusCodeNotFound = 404; +const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429; +const int kGULNetworkHTTPStatusCodeUnavailable = 503; + +NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain"; + +GULLoggerService kGULLoggerNetwork = @"[GULNetwork]"; diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m new file mode 100644 index 0000000..416a736 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m @@ -0,0 +1,740 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "Private/GULNetworkURLSession.h" + +#import +#import "Private/GULMutableDictionary.h" +#import "Private/GULNetworkConstants.h" +#import "Private/GULNetworkMessageCode.h" + +@interface GULNetworkURLSession () +@end + +@implementation GULNetworkURLSession { + /// The handler to be called when the request completes or error has occurs. + GULNetworkURLSessionCompletionHandler _completionHandler; + + /// Session ID generated randomly with a fixed prefix. + NSString *_sessionID; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + /// The session configuration. NSURLSessionConfiguration' is only available on iOS 7.0 or newer. + NSURLSessionConfiguration *_sessionConfig; + + /// The current NSURLSession. + NSURLSession *__weak _Nullable _URLSession; +#pragma clang diagnostic pop + + /// The path to the directory where all temporary files are stored before uploading. + NSURL *_networkDirectoryURL; + + /// The downloaded data from fetching. + NSData *_downloadedData; + + /// The path to the temporary file which stores the uploading data. + NSURL *_uploadingFileURL; + + /// The current request. + NSURLRequest *_request; +} + +#pragma mark - Init + +- (instancetype)initWithNetworkLoggerDelegate:(id)networkLoggerDelegate { + self = [super init]; + if (self) { + // Create URL to the directory where all temporary files to upload have to be stored. + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *applicationSupportDirectory = paths.firstObject; + NSArray *tempPathComponents = @[ + applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory, + kGULNetworkTempDirectoryName + ]; + _networkDirectoryURL = [NSURL fileURLWithPathComponents:tempPathComponents]; + _sessionID = [NSString stringWithFormat:@"%@-%@", kGULNetworkBackgroundSessionConfigIDPrefix, + [[NSUUID UUID] UUIDString]]; + _loggerDelegate = networkLoggerDelegate; + } + return self; +} + +#pragma mark - External Methods + +#pragma mark - To be called from AppDelegate + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler: + (GULNetworkSystemCompletionHandler)systemCompletionHandler { + // The session may not be Analytics background. Ignore those that do not have the prefix. + if (![sessionID hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + return; + } + GULNetworkURLSession *fetcher = [self fetcherWithSessionIdentifier:sessionID]; + if (fetcher != nil) { + [fetcher addSystemCompletionHandler:systemCompletionHandler forSession:sessionID]; + } else { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork003], + @"Failed to retrieve background session with ID %@ after app is relaunched.", + sessionID); + } +} + +#pragma mark - External Methods + +/// Sends an async POST request using NSURLSession for iOS >= 7.0, and returns an ID of the +/// connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + // NSURLSessionUploadTask does not work with NSData in the background. + // To avoid this issue, write the data to a temporary file to upload it. + // Make a temporary file with the data subset. + _uploadingFileURL = [self temporaryFilePathWithSessionID:_sessionID]; + NSError *writeError; + NSURLSessionUploadTask *postRequestTask; + NSURLSession *session; + BOOL didWriteFile = NO; + + // Clean up the entire temp folder to avoid temp files that remain in case the previous session + // crashed and did not clean up. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // If there is no background network enabled, no need to write to file. This will allow default + // network session which runs on the foreground. + if (_backgroundNetworkEnabled && [self ensureTemporaryDirectoryExists]) { + didWriteFile = [request.HTTPBody writeToFile:_uploadingFileURL.path + options:NSDataWritingAtomic + error:&writeError]; + + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession000 + message:@"Failed to write request data to file" + context:writeError]; + } + } + + if (didWriteFile) { + // Exclude this file from backing up to iTunes. There are conflicting reports that excluding + // directory from backing up does not exclude files of that directory from backing up. + [self excludeFromBackupForURL:_uploadingFileURL]; + + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromFile:_uploadingFileURL]; + } else { + // If we cannot write to file, just send it in the foreground. + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromData:request.HTTPBody]; + } + + if (!session || !postRequestTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + // Store completion handler because background session does not accept handler block but custom + // delegate. + _completionHandler = [handler copy]; + [postRequestTask resume]; + + return _sessionID; +} + +/// Sends an async GET request using NSURLSession for iOS >= 7.0, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + if (_backgroundNetworkEnabled) { + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + } else { + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + } + + [self populateSessionConfig:_sessionConfig withRequest:request]; + + // Do not cache the GET request. + _sessionConfig.URLCache = nil; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; + + if (!session || !downloadTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + _completionHandler = [handler copy]; + [downloadTask resume]; + + return _sessionID; +} + +#pragma mark - NSURLSessionTaskDelegate + +/// Called by the NSURLSession once the download task is completed. The file is saved in the +/// provided URL so we need to read the data and store into _downloadedData. Once the session is +/// completed, URLSession:task:didCompleteWithError will be called and the completion handler will +/// be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:(NSURL *)url API_AVAILABLE(ios(7.0)) { + if (!url.path) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession001 + message:@"Unable to read downloaded data from empty temp path"]; + _downloadedData = nil; + return; + } + + NSError *error; + _downloadedData = [NSData dataWithContentsOfFile:url.path options:0 error:&error]; + + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession002 + message:@"Cannot read the content of downloaded data" + context:error]; + _downloadedData = nil; + } +} + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session + API_AVAILABLE(ios(7.0)) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession003 + message:@"Background session finished" + context:session.configuration.identifier]; + [self callSystemCompletionHandler:session.configuration.identifier]; +} +#endif + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error API_AVAILABLE(ios(7.0)) { + // Avoid any chance of recursive behavior leading to it being used repeatedly. + GULNetworkURLSessionCompletionHandler handler = _completionHandler; + _completionHandler = nil; + + if (task.response) { + // The following assertion should always be true for HTTP requests, see https://goo.gl/gVLxT7. + NSAssert([task.response isKindOfClass:[NSHTTPURLResponse class]], @"URL response must be HTTP"); + + // The server responded so ignore the error created by the system. + error = nil; + } else if (!error) { + error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkInvalidResponse + userInfo:@{kGULNetworkErrorContext : @"Network Error: Empty network response"}]; + } + + [self callCompletionHandler:handler + withResponse:(NSHTTPURLResponse *)task.response + data:_downloadedData + error:error]; + + // Remove the temp file to avoid trashing devices with lots of temp files. + [self removeTempItemAtURL:_uploadingFileURL]; + + // Try to clean up stale files again. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // This is called without checking the sessionID here since non-background sessions + // won't have an ID. + [session finishTasksAndInvalidate]; + + // Explicitly remove the session so it won't be reused. The weak map table should + // remove the session on deallocation, but dealloc may not happen immediately after + // calling `finishTasksAndInvalidate`. + NSString *sessionID = session.configuration.identifier; + [[self class] setSessionInFetcherMap:nil forSessionID:sessionID]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential *credential))completionHandler + API_AVAILABLE(ios(7.0)) { + // The handling is modeled after GTMSessionFetcher. + if ([challenge.protectionSpace.authenticationMethod + isEqualToString:NSURLAuthenticationMethodServerTrust]) { + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession004 + message:@"Received empty server trust for host. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + return; + } + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + if (!credential) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession005 + message:@"Unable to verify server identity. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + return; + } + + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession006 + message:@"Received SSL challenge for host. Host" + context:_request.URL]; + + void (^callback)(BOOL) = ^(BOOL allow) { + if (allow) { + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + [self->_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession007 + message:@"Cancelling authentication challenge for host. Host" + context:self->_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_async(evaluateBackgroundQueue, ^{ + SecTrustResultType trustEval = kSecTrustResultInvalid; + BOOL shouldAllow; + OSStatus trustError; + + @synchronized([GULNetworkURLSession class]) { + trustError = SecTrustEvaluate(serverTrust, &trustEval); + } + + if (trustError != errSecSuccess) { + [self->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession008 + message:@"Cannot evaluate server trust. Error, host" + contexts:@[ @(trustError), self->_request.URL ]]; + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + shouldAllow = + (trustEval == kSecTrustResultUnspecified || trustEval == kSecTrustResultProceed); + } + + // Call the call back with the permission. + callback(shouldAllow); + + CFRelease(serverTrust); + }); + return; + } + + // Default handling for other Auth Challenges. + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} + +#pragma mark - Internal Methods + +/// Stores system completion handler with session ID as key. +- (void)addSystemCompletionHandler:(GULNetworkSystemCompletionHandler)handler + forSession:(NSString *)identifier { + if (!handler) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession009 + message:@"Cannot store nil system completion handler in network"]; + return; + } + + if (!identifier.length) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession010 + message:@"Cannot store system completion handler with empty network " + "session identifier"]; + return; + } + + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + if (systemCompletionHandlers[identifier]) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession011 + message:@"Got multiple system handlers for a single session ID" + context:identifier]; + } + + systemCompletionHandlers[identifier] = handler; +} + +/// Calls the system provided completion handler with the session ID stored in the dictionary. +/// The handler will be removed from the dictionary after being called. +- (void)callSystemCompletionHandler:(NSString *)identifier { + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + GULNetworkSystemCompletionHandler handler = [systemCompletionHandlers objectForKey:identifier]; + + if (handler) { + [systemCompletionHandlers removeObjectForKey:identifier]; + + dispatch_async(dispatch_get_main_queue(), ^{ + handler(); + }); + } +} + +/// Sets or updates the session ID of this session. +- (void)setSessionID:(NSString *)sessionID { + _sessionID = [sessionID copy]; +} + +/// Creates a background session configuration with the session ID using the supported method. +- (NSURLSessionConfiguration *)backgroundSessionConfigWithSessionID:(NSString *)sessionID + API_AVAILABLE(ios(7.0)) { +#if (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10) || \ + TARGET_OS_TV || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) + + // iOS 8/10.10 builds require the new backgroundSessionConfiguration method name. + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; + +#elif (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0) + + // Do a runtime check to avoid a deprecation warning about using + // +backgroundSessionConfiguration: on iOS 8. + if ([NSURLSessionConfiguration + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + // Running on iOS 8+/OS X 10.10+. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; +#pragma clang diagnostic pop + } else { + // Running on iOS 7/OS X 10.9. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; + } + +#else + // Building with an SDK earlier than iOS 8/OS X 10.10. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; +#endif +} + +- (void)maybeRemoveTempFilesAtURL:(NSURL *)folderURL expiringTime:(NSTimeInterval)staleTime { + if (!folderURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + NSArray *properties = @[ NSURLCreationDateKey ]; + NSArray *directoryContent = + [fileManager contentsOfDirectoryAtURL:folderURL + includingPropertiesForKeys:properties + options:NSDirectoryEnumerationSkipsSubdirectoryDescendants + error:&error]; + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession012 + message:@"Cannot get files from the temporary network folder. Error" + context:error]; + return; + } + + if (!directoryContent.count) { + return; + } + + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + for (NSURL *tempFile in directoryContent) { + NSDate *creationDate; + BOOL getCreationDate = [tempFile getResourceValue:&creationDate + forKey:NSURLCreationDateKey + error:NULL]; + if (!getCreationDate) { + continue; + } + NSTimeInterval creationTimeInterval = creationDate.timeIntervalSince1970; + if (fabs(now - creationTimeInterval) > staleTime) { + [self removeTempItemAtURL:tempFile]; + } + } +} + +/// Removes the temporary file written to disk for sending the request. It has to be cleaned up +/// after the session is done. +- (void)removeTempItemAtURL:(NSURL *)fileURL { + if (!fileURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + if (![fileManager removeItemAtURL:fileURL error:&error] && error.code != NSFileNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession013 + message:@"Failed to remove temporary uploading data file. Error" + context:error.localizedDescription]; + } +} + +/// Gets the fetcher with the session ID. ++ (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GULNetworkURLSession *session = [self sessionFromFetcherMapForSessionID:sessionIdentifier]; + if (!session && [sessionIdentifier hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + session = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:nil]; + [session setSessionID:sessionIdentifier]; + [self setSessionInFetcherMap:session forSessionID:sessionIdentifier]; + } + return session; +} + +/// Returns a map of the fetcher by session ID. Creates a map if it is not created. +/// When reading and writing from/to the session map, don't use this method directly. +/// To avoid thread safety issues, use one of the helper methods at the bottom of the +/// file: setSessionInFetcherMap:forSessionID:, sessionFromFetcherMapForSessionID: ++ (NSMapTable *)sessionIDToFetcherMap { + static NSMapTable *sessionIDToFetcherMap; + + static dispatch_once_t sessionMapOnceToken; + dispatch_once(&sessionMapOnceToken, ^{ + sessionIDToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return sessionIDToFetcherMap; +} + ++ (NSLock *)sessionIDToFetcherMapReadWriteLock { + static NSLock *lock; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + return lock; +} + +/// Returns a map of system provided completion handler by session ID. Creates a map if it is not +/// created. ++ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary { + static GULMutableDictionary *systemCompletionHandlers; + + static dispatch_once_t systemCompletionHandlerOnceToken; + dispatch_once(&systemCompletionHandlerOnceToken, ^{ + systemCompletionHandlers = [[GULMutableDictionary alloc] init]; + }); + return systemCompletionHandlers; +} + +- (NSURL *)temporaryFilePathWithSessionID:(NSString *)sessionID { + NSString *tempName = [NSString stringWithFormat:@"GULUpload_temp_%@", sessionID]; + return [_networkDirectoryURL URLByAppendingPathComponent:tempName]; +} + +/// Makes sure that the directory to store temp files exists. If not, tries to create it and returns +/// YES. If there is anything wrong, returns NO. +- (BOOL)ensureTemporaryDirectoryExists { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + // Create a temporary directory if it does not exist or was deleted. + if ([_networkDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + return YES; + } + + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession014 + message:@"Error while trying to access Network temp folder. Error" + context:error]; + } + + NSError *writeError = nil; + + [fileManager createDirectoryAtURL:_networkDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&writeError]; + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession015 + message:@"Cannot create temporary directory. Error" + context:writeError]; + return NO; + } + + // Set the iCloud exclusion attribute on the Documents URL. + [self excludeFromBackupForURL:_networkDirectoryURL]; + + return YES; +} + +- (void)excludeFromBackupForURL:(NSURL *)url { + if (!url.path) { + return; + } + + // Set the iCloud exclusion attribute on the Documents URL. + NSError *preventBackupError = nil; + [url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&preventBackupError]; + if (preventBackupError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession016 + message:@"Cannot exclude temporary folder from iTunes backup"]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler API_AVAILABLE(ios(7.0)) { + NSArray *nonAllowedRedirectionCodes = @[ + @(kGULNetworkHTTPStatusCodeFound), @(kGULNetworkHTTPStatusCodeMovedPermanently), + @(kGULNetworkHTTPStatusCodeMovedTemporarily), @(kGULNetworkHTTPStatusCodeMultipleChoices) + ]; + + // Allow those not in the non allowed list to be followed. + if (![nonAllowedRedirectionCodes containsObject:@(response.statusCode)]) { + completionHandler(request); + return; + } + + // Do not allow redirection if the response code is in the non-allowed list. + NSURLRequest *newRequest = request; + + if (response) { + newRequest = nil; + } + + completionHandler(newRequest); +} + +#pragma mark - Helper Methods + ++ (void)setSessionInFetcherMap:(GULNetworkURLSession *)session forSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *existingSession = + [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + if (existingSession) { + if (session) { + NSString *message = [NSString stringWithFormat:@"Discarding session: %@", existingSession]; + [existingSession->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelInfo + messageCode:kGULNetworkMessageCodeURLSession019 + message:message]; + } + [existingSession->_URLSession finishTasksAndInvalidate]; + } + if (session) { + [[[self class] sessionIDToFetcherMap] setObject:session forKey:sessionID]; + } else { + [[[self class] sessionIDToFetcherMap] removeObjectForKey:sessionID]; + } + [[self sessionIDToFetcherMapReadWriteLock] unlock]; +} + ++ (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *session = [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + [[self sessionIDToFetcherMapReadWriteLock] unlock]; + return session; +} + +- (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler + withResponse:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession017 + message:@"Encounter network error. Code, error" + contexts:@[ @(error.code), error ]]; + } + + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(response, data, self->_sessionID, error); + }); + } +} + +// Always use the request parameters even if the default session configuration is more restrictive. +- (void)populateSessionConfig:(NSURLSessionConfiguration *)sessionConfig + withRequest:(NSURLRequest *)request API_AVAILABLE(ios(7.0)) { + sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields; + sessionConfig.timeoutIntervalForRequest = request.timeoutInterval; + sessionConfig.timeoutIntervalForResource = request.timeoutInterval; + sessionConfig.requestCachePolicy = request.cachePolicy; +} + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h new file mode 100644 index 0000000..a8cc45b --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// A mutable dictionary that provides atomic accessor and mutators. +@interface GULMutableDictionary : NSObject + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKey:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)object forKey:(id)key; + +/// Removes the object given its session ID from the dictionary. +- (void)removeObjectForKey:(id)key; + +/// Removes all objects. +- (void)removeAllObjects; + +/// Returns the number of current objects in the dictionary. +- (NSUInteger)count; + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKeyedSubscript:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key; + +/// Returns the immutable dictionary. +- (NSDictionary *)dictionary; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h new file mode 100644 index 0000000..0e75ae5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkConstants.h" +#import "GULNetworkLoggerProtocol.h" +#import "GULNetworkURLSession.h" + +/// Delegate protocol for GULNetwork events. +@protocol GULNetworkReachabilityDelegate + +/// Tells the delegate to handle events when the network reachability changes to connected or not +/// connected. +- (void)reachabilityDidChange; + +@end + +/// The Network component that provides network status and handles network requests and responses. +/// This is not thread safe. +/// +/// NOTE: +/// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the +/// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler: +@interface GULNetwork : NSObject + +/// Indicates if network connectivity is available. +@property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected; + +/// Indicates if there are any uploads in progress. +@property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress; + +/// An optional delegate that can be used in the event when network reachability changes. +@property(nonatomic, weak) id reachabilityDelegate; + +/// An optional delegate that can be used to log messages, warnings or errors that occur in the +/// network operations. +@property(nonatomic, weak) id loggerDelegate; + +/// Indicates whether the logger should display debug messages. +@property(nonatomic, assign) BOOL isDebugModeEnabled; + +/// The time interval in seconds for the network request to timeout. +@property(nonatomic, assign) NSTimeInterval timeoutInterval; + +/// Initializes with the default reachability host. +- (instancetype)init; + +/// Initializes with a custom reachability host. +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost; + +/// Handles events when background session with the given ID has finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Compresses and sends a POST request with the provided data to the URL. The session will be +/// background session if usingBackgroundSession is YES. Otherwise, the POST session is default +/// session. Returns a session ID or nil if an error occurs. +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +/// Sends a GET request with the provided data to the URL. The session will be background session +/// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a +/// session ID or nil if an error occurs. +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h new file mode 100644 index 0000000..44d440b --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Error codes in Firebase Network error domain. +/// Note: these error codes should never change. It would make it harder to decode the errors if +/// we inadvertently altered any of these codes in a future SDK version. +typedef NS_ENUM(NSInteger, GULNetworkErrorCode) { + /// Unknown error. + GULNetworkErrorCodeUnknown = 0, + /// Error occurs when the request URL is invalid. + GULErrorCodeNetworkInvalidURL = 1, + /// Error occurs when request cannot be constructed. + GULErrorCodeNetworkRequestCreation = 2, + /// Error occurs when payload cannot be compressed. + GULErrorCodeNetworkPayloadCompression = 3, + /// Error occurs when session task cannot be created. + GULErrorCodeNetworkSessionTaskCreation = 4, + /// Error occurs when there is no response. + GULErrorCodeNetworkInvalidResponse = 5 +}; + +#pragma mark - Network constants + +/// The prefix of the ID of the background session. +extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix; + +/// The sub directory to store the files of data that is being uploaded in the background. +extern NSString *const kGULNetworkApplicationSupportSubdirectory; + +/// Name of the temporary directory that stores files for background uploading. +extern NSString *const kGULNetworkTempDirectoryName; + +/// The period when the temporary uploading file can stay. +extern const NSTimeInterval kGULNetworkTempFolderExpireTime; + +/// The default network request timeout interval. +extern const NSTimeInterval kGULNetworkTimeOutInterval; + +/// The host to check the reachability of the network. +extern NSString *const kGULNetworkReachabilityHost; + +/// The key to get the error context of the UserInfo. +extern NSString *const kGULNetworkErrorContext; + +#pragma mark - Network Status Code + +extern const int kGULNetworkHTTPStatusOK; +extern const int kGULNetworkHTTPStatusNoContent; +extern const int kGULNetworkHTTPStatusCodeMultipleChoices; +extern const int kGULNetworkHTTPStatusCodeMovedPermanently; +extern const int kGULNetworkHTTPStatusCodeFound; +extern const int kGULNetworkHTTPStatusCodeNotModified; +extern const int kGULNetworkHTTPStatusCodeMovedTemporarily; +extern const int kGULNetworkHTTPStatusCodeNotFound; +extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic; +extern const int kGULNetworkHTTPStatusCodeUnavailable; + +#pragma mark - Error Domain + +extern NSString *const kGULNetworkErrorDomain; + +/// The logger service for GULNetwork. +extern GULLoggerService kGULLoggerNetwork; diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h new file mode 100644 index 0000000..f1be590 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GULNetworkMessageCode.h" + +/// The log levels used by GULNetworkLogger. +typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { + kGULNetworkLogLevelError = GULLoggerLevelError, + kGULNetworkLogLevelWarning = GULLoggerLevelWarning, + kGULNetworkLogLevelInfo = GULLoggerLevelInfo, + kGULNetworkLogLevelDebug = GULLoggerLevelDebug, +}; + +@protocol GULNetworkLoggerDelegate + +@required +/// Tells the delegate to log a message with an array of contexts and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts; + +/// Tells the delegate to log a message with a context and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context; + +/// Tells the delegate to log a message with the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h new file mode 100644 index 0000000..f9d1628 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULNetworkMessageCode) { + // GULNetwork.m + kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000 + kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001 + kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002 + kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003 + // GULNetworkURLSession.m + kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000 + kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001 + kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002 + kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003 + kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004 + kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005 + kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006 + kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007 + kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008 + kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009 + kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010 + kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011 + kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012 + kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013 + kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014 + kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015 + kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016 + kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017 + kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018 + kGULNetworkMessageCodeURLSession019 = 901019, // I-NET901019 +}; diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h new file mode 100644 index 0000000..3f9f7f9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkLoggerProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSError *_Nullable error); +typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSString *sessionID, + NSError *_Nullable error); +typedef void (^GULNetworkSystemCompletionHandler)(void); + +/// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses. +@interface GULNetworkURLSession : NSObject + +/// Indicates whether the background network is enabled. Default value is NO. +@property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled; + +/// The logger delegate to log message, errors or warnings that occur during the network operations. +@property(nonatomic, weak, nullable) id loggerDelegate; + +/// Calls the system provided completion handler after the background session is finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Initializes with logger delegate. +- (instancetype)initWithNetworkLoggerDelegate: + (nullable id)networkLoggerDelegate NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Sends an asynchronous POST request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session/connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +/// Sends an asynchronous GET request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +NS_ASSUME_NONNULL_END +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h new file mode 100644 index 0000000..8883c4d --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, + const char *host); + +typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callback, + SCNetworkReachabilityContext *context); +typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); +typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); + +typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf); + +struct GULReachabilityApi { + GULReachabilityCreateWithNameFn createWithNameFn; + GULReachabilitySetCallbackFn setCallbackFn; + GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn; + GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn; + GULReachabilityReleaseFn releaseFn; +}; + +@interface GULReachabilityChecker (Internal) + +- (const struct GULReachabilityApi *)reachabilityApi; +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m new file mode 100644 index 0000000..1ddacdf --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m @@ -0,0 +1,240 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GULReachabilityChecker+Internal.h" +#import "Private/GULReachabilityChecker.h" +#import "Private/GULReachabilityMessageCode.h" + +#import +#import + +static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; + +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +static const struct GULReachabilityApi kGULDefaultReachabilityApi = { + SCNetworkReachabilityCreateWithName, + SCNetworkReachabilitySetCallback, + SCNetworkReachabilityScheduleWithRunLoop, + SCNetworkReachabilityUnscheduleFromRunLoop, + CFRelease, +}; + +static NSString *const kGULReachabilityUnknownStatus = @"Unknown"; +static NSString *const kGULReachabilityConnectedStatus = @"Connected"; +static NSString *const kGULReachabilityDisconnectedStatus = @"Disconnected"; + +@interface GULReachabilityChecker () + +@property(nonatomic, assign) const struct GULReachabilityApi *reachabilityApi; +@property(nonatomic, assign) GULReachabilityStatus reachabilityStatus; +@property(nonatomic, copy) NSString *host; +@property(nonatomic, assign) SCNetworkReachabilityRef reachability; + +@end + +@implementation GULReachabilityChecker + +@synthesize reachabilityApi = reachabilityApi_; +@synthesize reachability = reachability_; + +- (const struct GULReachabilityApi *)reachabilityApi { + return reachabilityApi_; +} + +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi { + if (reachability_) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode000], + @"Cannot change reachability API while reachability is running. " + @"Call stop first."); + return; + } + reachabilityApi_ = reachabilityApi; +} + +@synthesize reachabilityStatus = reachabilityStatus_; +@synthesize host = host_; +@synthesize reachabilityDelegate = reachabilityDelegate_; + +- (BOOL)isActive { + return reachability_ != nil; +} + +- (void)setReachabilityDelegate:(id)reachabilityDelegate { + if (reachabilityDelegate && + (![(NSObject *)reachabilityDelegate conformsToProtocol:@protocol(GULReachabilityDelegate)])) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULReachabilityMessageCode005], + @"Reachability delegate doesn't conform to Reachability protocol."); + return; + } + reachabilityDelegate_ = reachabilityDelegate; +} + +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host { + self = [super init]; + + if (!host || !host.length) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode001], + @"Invalid host specified"); + return nil; + } + if (self) { + [self setReachabilityDelegate:reachabilityDelegate]; + reachabilityApi_ = &kGULDefaultReachabilityApi; + reachabilityStatus_ = kGULReachabilityUnknown; + host_ = [host copy]; + reachability_ = nil; + } + return self; +} + +- (void)dealloc { + reachabilityDelegate_ = nil; + [self stop]; +} + +- (BOOL)start { + if (!reachability_) { + reachability_ = reachabilityApi_->createWithNameFn(kCFAllocatorDefault, [host_ UTF8String]); + if (!reachability_) { + return NO; + } + SCNetworkReachabilityContext context = { + 0, /* version */ + (__bridge void *)(self), /* info (passed as last parameter to reachability callback) */ + NULL, /* retain */ + NULL, /* release */ + NULL /* copyDescription */ + }; + if (!reachabilityApi_->setCallbackFn(reachability_, ReachabilityCallback, &context) || + !reachabilityApi_->scheduleWithRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes)) { + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode002], + @"Failed to start reachability handle"); + return NO; + } + } + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode003], + @"Monitoring the network status"); + return YES; +} + +- (void)stop { + if (reachability_) { + reachabilityStatus_ = kGULReachabilityUnknown; + reachabilityApi_->unscheduleFromRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes); + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + } +} + +- (GULReachabilityStatus)statusForFlags:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = kGULReachabilityNotReachable; + // If the Reachable flag is not set, we definitely don't have connectivity. + if (flags & kSCNetworkReachabilityFlagsReachable) { + // Reachable flag is set. Check further flags. + if (!(flags & kSCNetworkReachabilityFlagsConnectionRequired)) { +// Connection required flag is not set, so we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } else if ((flags & (kSCNetworkReachabilityFlagsConnectionOnDemand | + kSCNetworkReachabilityFlagsConnectionOnTraffic)) && + !(flags & kSCNetworkReachabilityFlagsInterventionRequired)) { +// If the connection on demand or connection on traffic flag is set, and user intervention +// is not required, we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } + } + return status; +} + +- (void)reachabilityFlagsChanged:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = [self statusForFlags:flags]; + if (reachabilityStatus_ != status) { + NSString *reachabilityStatusString; + if (status == kGULReachabilityUnknown) { + reachabilityStatusString = kGULReachabilityUnknownStatus; + } else { + reachabilityStatusString = (status == kGULReachabilityNotReachable) + ? kGULReachabilityDisconnectedStatus + : kGULReachabilityConnectedStatus; + } + + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode004], + @"Network status has changed. Code:%@, status:%@", @(status), + reachabilityStatusString); + reachabilityStatus_ = status; + [reachabilityDelegate_ reachability:self statusChanged:reachabilityStatus_]; + } +} + +@end + +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GULReachabilityChecker *checker = (__bridge GULReachabilityChecker *)info; + [checker reachabilityFlagsChanged:flags]; +} + +// This function used to be at the top of the file, but it was moved here +// as a workaround for a suspected compiler bug. When compiled in Release mode +// and run on an iOS device with WiFi disabled, the reachability code crashed +// when calling SCNetworkReachabilityScheduleWithRunLoop, or shortly thereafter. +// After unsuccessfully trying to diagnose the cause of the crash, it was +// discovered that moving this function to the end of the file magically fixed +// the crash. If you are going to edit this file, exercise caution and make sure +// to test thoroughly with an iOS device under various network conditions. +const NSString *GULReachabilityStatusString(GULReachabilityStatus status) { + switch (status) { + case kGULReachabilityUnknown: + return @"Reachability Unknown"; + + case kGULReachabilityNotReachable: + return @"Not reachable"; + + case kGULReachabilityViaWifi: + return @"Reachable via Wifi"; + + case kGULReachabilityViaCellular: + return @"Reachable via Cellular Data"; + + default: + return [NSString stringWithFormat:@"Invalid reachability status %d", (int)status]; + } +} diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h new file mode 100644 index 0000000..b317a0b --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Reachability Status +typedef enum { + kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable. + kGULReachabilityNotReachable, ///< Host is not reachable. + kGULReachabilityViaWifi, ///< Host is reachable via Wifi. + kGULReachabilityViaCellular, ///< Host is reachable via cellular. +} GULReachabilityStatus; + +const NSString *GULReachabilityStatusString(GULReachabilityStatus status); + +@class GULReachabilityChecker; + +/// Google Analytics iOS Reachability Checker. +@protocol GULReachabilityDelegate +@required +/// Called when network status has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status; +@end + +/// Google Analytics iOS Network Status Checker. +@interface GULReachabilityChecker : NSObject + +/// The last known reachability status, or GULReachabilityStatusUnknown if the +/// checker is not active. +@property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus; +/// The host to which reachability status is to be checked. +@property(nonatomic, copy, readonly) NSString *host; +/// The delegate to be notified of reachability status changes. +@property(nonatomic, weak) id reachabilityDelegate; +/// `YES` if the reachability checker is active, `NO` otherwise. +@property(nonatomic, readonly) BOOL isActive; + +/// Initialize the reachability checker. Note that you must call start to begin checking for and +/// receiving notifications about network status changes. +/// +/// @param reachabilityDelegate The delegate to be notified when reachability status to host +/// changes. +/// +/// @param host The name of the host. +/// +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host; + +- (instancetype)init NS_UNAVAILABLE; + +/// Start checking for reachability to the specified host. This has no effect if the status +/// checker is already checking for connectivity. +/// +/// @return `YES` if initiating status checking was successful or the status checking has already +/// been initiated, `NO` otherwise. +- (BOOL)start; + +/// Stop checking for reachability to the specified host. This has no effect if the status +/// checker is not checking for connectivity. +- (void)stop; + +@end diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h new file mode 100644 index 0000000..283cdd5 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULReachabilityMessageCode) { + // GULReachabilityChecker.m + kGULReachabilityMessageCode000 = 902000, // I-NET902000 + kGULReachabilityMessageCode001 = 902001, // I-NET902001 + kGULReachabilityMessageCode002 = 902002, // I-NET902002 + kGULReachabilityMessageCode003 = 902003, // I-NET902003 + kGULReachabilityMessageCode004 = 902004, // I-NET902004 + kGULReachabilityMessageCode005 = 902005, // I-NET902005 + kGULReachabilityMessageCode006 = 902006, // I-NET902006 +}; diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m new file mode 100644 index 0000000..ac497b2 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m @@ -0,0 +1,235 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULUserDefaults.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +static NSTimeInterval const kGULSynchronizeInterval = 1.0; + +static NSString *const kGULLogFormat = @"I-GUL%06ld"; + +static GULLoggerService kGULLogUserDefaultsService = @"[GoogleUtilities/UserDefaults]"; + +typedef NS_ENUM(NSInteger, GULUDMessageCode) { + GULUDMessageCodeInvalidKeyGet = 1, + GULUDMessageCodeInvalidKeySet = 2, + GULUDMessageCodeInvalidObjectSet = 3, + GULUDMessageCodeSynchronizeFailed = 4, +}; + +@interface GULUserDefaults () + +/// Equivalent to the suite name for NSUserDefaults. +@property(readonly) CFStringRef appNameRef; + +@property(atomic) BOOL isPreferenceFileExcluded; + +@end + +@implementation GULUserDefaults { + // The application name is the same with the suite name of the NSUserDefaults, and it is used for + // preferences. + CFStringRef _appNameRef; +} + ++ (GULUserDefaults *)standardUserDefaults { + static GULUserDefaults *standardUserDefaults; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[GULUserDefaults alloc] init]; + }); + return standardUserDefaults; +} + +- (instancetype)init { + return [self initWithSuiteName:nil]; +} + +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName { + self = [super init]; + + NSString *name = [suiteName copy]; + + if (self) { + // `kCFPreferencesCurrentApplication` maps to the same defaults database as + // `[NSUserDefaults standardUserDefaults]`. + _appNameRef = + name.length ? (__bridge_retained CFStringRef)name : kCFPreferencesCurrentApplication; + } + + return self; +} + +- (void)dealloc { + // If we're using a custom `_appNameRef` it needs to be released. If it's a constant, it shouldn't + // need to be released since we don't own it. + if (CFStringCompare(_appNameRef, kCFPreferencesCurrentApplication, 0) != kCFCompareEqualTo) { + CFRelease(_appNameRef); + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; +} + +- (nullable id)objectForKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(@"", NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeyGet], + @"Cannot get object for invalid user default key."); + return nil; + } + return (__bridge_transfer id)CFPreferencesCopyAppValue((__bridge CFStringRef)key, _appNameRef); +} + +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeySet], + @"Cannot set object for invalid user default key."); + return; + } + if (!value) { + CFPreferencesSetAppValue((__bridge CFStringRef)key, NULL, _appNameRef); + [self scheduleSynchronize]; + return; + } + BOOL isAcceptableValue = + [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] || + [value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] || + [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]]; + if (!isAcceptableValue) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidObjectSet], + @"Cannot set invalid object to user defaults. Must be a string, number, array, " + @"dictionary, date, or data. Value: %@", + value); + return; + } + + CFPreferencesSetAppValue((__bridge CFStringRef)key, (__bridge CFStringRef)value, _appNameRef); + [self scheduleSynchronize]; +} + +- (void)removeObjectForKey:(NSString *)key { + [self setObject:nil forKey:key]; +} + +#pragma mark - Getters + +- (NSInteger)integerForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.integerValue; +} + +- (float)floatForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.floatValue; +} + +- (double)doubleForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.doubleValue; +} + +- (BOOL)boolForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.boolValue; +} + +- (nullable NSString *)stringForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSArray *)arrayForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +#pragma mark - Setters + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)defaultName { + [self setObject:@(integer) forKey:defaultName]; +} + +- (void)setFloat:(float)value forKey:(NSString *)defaultName { + [self setObject:@(value) forKey:defaultName]; +} + +- (void)setDouble:(double)doubleNumber forKey:(NSString *)defaultName { + [self setObject:@(doubleNumber) forKey:defaultName]; +} + +- (void)setBool:(BOOL)boolValue forKey:(NSString *)defaultName { + [self setObject:@(boolValue) forKey:defaultName]; +} + +#pragma mark - Save data + +- (void)synchronize { + if (!CFPreferencesAppSynchronize(_appNameRef)) { + GULLogError(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeSynchronizeFailed], + @"Cannot synchronize user defaults to disk"); + } +} + +#pragma mark - Private methods + +/// Removes all values from the search list entry specified by 'domainName', the current user, and +/// any host. The change is persistent. Equivalent to -removePersistentDomainForName: of +/// NSUserDefaults. +- (void)clearAllData { + // On macOS, using `kCFPreferencesCurrentHost` will not set all the keys necessary to match + // `NSUserDefaults`. +#if TARGET_OS_OSX + CFStringRef host = kCFPreferencesAnyHost; +#else + CFStringRef host = kCFPreferencesCurrentHost; +#endif // TARGET_OS_OSX + + CFArrayRef keyList = CFPreferencesCopyKeyList(_appNameRef, kCFPreferencesCurrentUser, host); + if (!keyList) { + return; + } + + CFPreferencesSetMultiple(NULL, keyList, _appNameRef, kCFPreferencesCurrentUser, host); + CFRelease(keyList); + [self scheduleSynchronize]; +} + +- (void)scheduleSynchronize { + // Synchronize data using a timer so that multiple set... calls can be coalesced under one + // synchronize. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; + // This method may be called on multiple queues (due to set... methods can be called on any queue) + // synchronize can be scheduled on different queues, so make sure that it does not crash. If this + // instance goes away, self will be released also, no one will retain it and the schedule won't be + // called. + [self performSelector:@selector(synchronize) withObject:nil afterDelay:kGULSynchronizeInterval]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h new file mode 100644 index 0000000..0d04781 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A thread-safe user defaults that uses C functions from CFPreferences.h instead of +/// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a +/// background thread to avoid crashing. // TODO: Insert radar number here. +@interface GULUserDefaults : NSObject + +/// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same +/// data of the standardUserDefaults. ++ (GULUserDefaults *)standardUserDefaults; + +/// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name. +/// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly +/// the same. +/// +/// @param suiteName The name of the suite of the user defaults. +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName; + +#pragma mark - Getters + +/// Searches the receiver's search list for a default with the key 'defaultName' and return it. If +/// another process has changed defaults in the search list, NSUserDefaults will automatically +/// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults +/// Configuration File, the latest value may not be immediately available, and the registered value +/// will be returned instead. +- (nullable id)objectForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray. +- (nullable NSArray *)arrayForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value +/// is not an NSDictionary. +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString +/// representation. If a non-string non-number value is found, nil will be returned. +- (nullable NSString *)stringForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the +/// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, +/// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted +/// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 +/// will be returned. +- (NSInteger)integerForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a float, and boolean values will not be +/// converted. +- (float)floatForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a double, and boolean values will not be +/// converted. +- (double)doubleForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value +/// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an +/// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string +/// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned. +- (BOOL)boolForKey:(NSString *)defaultName; + +#pragma mark - Setters + +/// Immediately stores a value (or removes the value if `nil` is passed as the value) for the +/// provided key in the search list entry for the receiver's suite name in the current user and any +/// host, then asynchronously stores the value persistently, where it is made available to other +/// processes. +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber. +- (void)setFloat:(float)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a double to an +/// NSNumber. +- (void)setDouble:(double)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an +/// NSNumber. +- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber. +- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; + +#pragma mark - Removing Defaults + +/// Equivalent to -[... setObject:nil forKey:defaultName] +- (void)removeObjectForKey:(NSString *)defaultName; + +#pragma mark - Save data + +/// Blocks the calling thread until all in-progress set operations have completed. +- (void)synchronize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/LICENSE b/PRODUCTNAME/app/Pods/GoogleUtilities/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PRODUCTNAME/app/Pods/GoogleUtilities/README.md b/PRODUCTNAME/app/Pods/GoogleUtilities/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/GoogleUtilities/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PRODUCTNAME/app/Pods/Headers/Private/Firebase/Firebase.h b/PRODUCTNAME/app/Pods/Headers/Private/Firebase/Firebase.h new file mode 120000 index 0000000..07ac6eb --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Private/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRAnalyticsInterop.h b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRAnalyticsInterop.h new file mode 120000 index 0000000..e01a43a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRAnalyticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRAnalyticsInteropListener.h b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRAnalyticsInteropListener.h new file mode 120000 index 0000000..d3cd097 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRAnalyticsInteropListener.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRInteropEventNames.h b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRInteropEventNames.h new file mode 120000 index 0000000..dbda3ec --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRInteropEventNames.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRInteropParameterNames.h b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRInteropParameterNames.h new file mode 120000 index 0000000..5145843 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Private/FirebaseAnalyticsInterop/FIRInteropParameterNames.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAI.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAI.h deleted file mode 120000 index 683db39..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAI.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAI.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIDictionaryBuilder.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIDictionaryBuilder.h deleted file mode 120000 index 52def70..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIDictionaryBuilder.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIDictionaryBuilder.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceFields.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceFields.h deleted file mode 120000 index b14b89e..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceFields.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommerceFields.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceProduct.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceProduct.h deleted file mode 120000 index b9ef4aa..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceProduct.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommerceProduct.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceProductAction.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceProductAction.h deleted file mode 120000 index 67e0a87..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommerceProductAction.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommerceProductAction.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommercePromotion.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommercePromotion.h deleted file mode 120000 index 3e9fcf8..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIEcommercePromotion.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommercePromotion.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIFields.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIFields.h deleted file mode 120000 index b79f2a9..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAIFields.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIFields.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAILogger.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAILogger.h deleted file mode 120000 index 8c57242..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAILogger.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAILogger.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAITrackedViewController.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAITrackedViewController.h deleted file mode 120000 index 45b0237..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAITrackedViewController.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAITrackedViewController.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAITracker.h b/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAITracker.h deleted file mode 120000 index 18574e3..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Private/GoogleAnalytics/GAITracker.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAITracker.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/Firebase/Firebase.h b/PRODUCTNAME/app/Pods/Headers/Public/Firebase/Firebase.h new file mode 120000 index 0000000..07ac6eb --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Public/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRAnalyticsInterop.h b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRAnalyticsInterop.h new file mode 120000 index 0000000..e01a43a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRAnalyticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRAnalyticsInteropListener.h b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRAnalyticsInteropListener.h new file mode 120000 index 0000000..d3cd097 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRAnalyticsInteropListener.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRInteropEventNames.h b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRInteropEventNames.h new file mode 120000 index 0000000..dbda3ec --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRInteropEventNames.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRInteropParameterNames.h b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRInteropParameterNames.h new file mode 120000 index 0000000..5145843 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Headers/Public/FirebaseAnalyticsInterop/FIRInteropParameterNames.h @@ -0,0 +1 @@ +../../../FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAI.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAI.h deleted file mode 120000 index 683db39..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAI.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAI.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIDictionaryBuilder.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIDictionaryBuilder.h deleted file mode 120000 index 52def70..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIDictionaryBuilder.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIDictionaryBuilder.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceFields.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceFields.h deleted file mode 120000 index b14b89e..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceFields.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommerceFields.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceProduct.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceProduct.h deleted file mode 120000 index b9ef4aa..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceProduct.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommerceProduct.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceProductAction.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceProductAction.h deleted file mode 120000 index 67e0a87..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommerceProductAction.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommerceProductAction.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommercePromotion.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommercePromotion.h deleted file mode 120000 index 3e9fcf8..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIEcommercePromotion.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIEcommercePromotion.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIFields.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIFields.h deleted file mode 120000 index b79f2a9..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAIFields.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAIFields.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAILogger.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAILogger.h deleted file mode 120000 index 8c57242..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAILogger.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAILogger.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAITrackedViewController.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAITrackedViewController.h deleted file mode 120000 index 45b0237..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAITrackedViewController.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAITrackedViewController.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAITracker.h b/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAITracker.h deleted file mode 120000 index 18574e3..0000000 --- a/PRODUCTNAME/app/Pods/Headers/Public/GoogleAnalytics/GAITracker.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleAnalytics/Sources/GAITracker.h \ No newline at end of file diff --git a/PRODUCTNAME/app/Pods/Manifest.lock b/PRODUCTNAME/app/Pods/Manifest.lock index cd52ee6..491ed15 100644 --- a/PRODUCTNAME/app/Pods/Manifest.lock +++ b/PRODUCTNAME/app/Pods/Manifest.lock @@ -1,13 +1,78 @@ PODS: - Alamofire (4.8.2) - Anchorage (4.3) + - AppCenter/Core (2.0.1) + - AppCenter/Distribute (2.0.1): + - AppCenter/Core - BonMot (5.3) - Crashlytics (3.12.0): - Fabric (~> 1.9.0) - Fabric (1.9.0) - - GoogleAnalytics (3.17.0) + - Firebase/Core (6.0.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.0.0) + - Firebase/CoreOnly (6.0.0): + - FirebaseCore (= 6.0.0) + - Firebase/Messaging (6.0.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 4.0.0) + - FirebaseAnalytics (6.0.0): + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleAppMeasurement (= 6.0.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - FirebaseAnalyticsInterop (1.2.0) + - FirebaseCore (6.0.0): + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Logger (~> 6.0) + - FirebaseInstanceID (4.0.0): + - FirebaseCore (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - FirebaseMessaging (4.0.0): + - FirebaseAnalyticsInterop (~> 1.1) + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Reachability (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - Protobuf (~> 3.1) + - GoogleAppMeasurement (6.0.0): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - GoogleUtilities/AppDelegateSwizzler (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.0.0) + - GoogleUtilities/Logger (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.0.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.0.0)" + - GoogleUtilities/Reachability (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.0.0): + - GoogleUtilities/Logger - Instabug (8.3) - KeychainAccess (3.2.0) + - nanopb (0.3.901): + - nanopb/decode (= 0.3.901) + - nanopb/encode (= 0.3.901) + - nanopb/decode (0.3.901) + - nanopb/encode (0.3.901) - OHHTTPStubs/Core (8.0.0) - OHHTTPStubs/Default (8.0.0): - OHHTTPStubs/Core @@ -21,6 +86,7 @@ PODS: - OHHTTPStubs/OHPathHelpers (8.0.0) - OHHTTPStubs/Swift (8.0.0): - OHHTTPStubs/Default + - Protobuf (3.7.0) - SimulatorStatusMagic (2.4.1) - Sourcery (0.16.1) - SwiftGen (6.1.0) @@ -89,9 +155,11 @@ PODS: DEPENDENCIES: - Alamofire - Anchorage + - AppCenter/Distribute - BonMot - Crashlytics - - GoogleAnalytics (~> 3.0) + - Firebase/Core + - Firebase/Messaging - Instabug - KeychainAccess - OHHTTPStubs/Swift @@ -105,13 +173,23 @@ SPEC REPOS: https://github.com/cocoapods/specs.git: - Alamofire - Anchorage + - AppCenter - BonMot - Crashlytics - Fabric - - GoogleAnalytics + - Firebase + - FirebaseAnalytics + - FirebaseAnalyticsInterop + - FirebaseCore + - FirebaseInstanceID + - FirebaseMessaging + - GoogleAppMeasurement + - GoogleUtilities - Instabug - KeychainAccess + - nanopb - OHHTTPStubs + - Protobuf - SimulatorStatusMagic - Sourcery - SwiftGen @@ -121,19 +199,29 @@ SPEC REPOS: SPEC CHECKSUMS: Alamofire: ae5c501addb7afdbb13687d7f2f722c78734c2d3 Anchorage: 21a98675245188427f0bcea21404d42a824a766f + AppCenter: 6a5ff2fd007b53431259fdd74f91eb3d0dfea3d1 BonMot: 0104d1b4eda54f4a4b7393d6559539ef25498fbd Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 Fabric: f988e33c97f08930a413e08123064d2e5f68d655 - GoogleAnalytics: f42cc53a87a51fe94334821868d9c8481ff47a7b + Firebase: fa80b9d987ca014a1ba9357496ef2a0178b28b12 + FirebaseAnalytics: 1743c5f4de3687d0745709dfdc4b1dea1484f44c + FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1 + FirebaseCore: e38f025287b413255a53acc1945d048a112047f7 + FirebaseInstanceID: 0e0348a3c00a734fa376a070f5ad4533ad975cb5 + FirebaseMessaging: c796d50864dc822a3c06c9c1c1444b37732b795b + GoogleAppMeasurement: 7f028ea162b72c8f326daec74afc95d94f7a47d6 + GoogleUtilities: f1faafc033ea203adf1783ce00af455bb99d0e5b Instabug: c61ac1b653b64596c1bd00cf5ba039f05aecb930 KeychainAccess: 3b1bf8a77eb4c6ea1ce9404c292e48f948954c6b + nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48 OHHTTPStubs: 9cbce6364bec557cc3439aa6bb7514670d780881 + Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a SimulatorStatusMagic: 28d4a9d1a500ac7cea0b2b5a43c1c6ddb40ba56c Sourcery: 16779170d35ee204666843b09031f36721a84bcc SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0 Swiftilities: 7b57b06b46df20236a1cd9faf64ab3fd7554f4ed SwiftLint: 009a898ef2a1c851f45e1b59349bf6ff2ddc990d -PODFILE CHECKSUM: f3cf654d6eed8a1c230b93a6ffde151bbf9179a5 +PODFILE CHECKSUM: f4deff92cb777959f68cae8d4fd0677ec3f2443f -COCOAPODS: 1.6.1 +COCOAPODS: 1.7.5 diff --git a/PRODUCTNAME/app/Pods/Pods.xcodeproj/project.pbxproj b/PRODUCTNAME/app/Pods/Pods.xcodeproj/project.pbxproj index fdc9b6a..c0d3c1d 100644 --- a/PRODUCTNAME/app/Pods/Pods.xcodeproj/project.pbxproj +++ b/PRODUCTNAME/app/Pods/Pods.xcodeproj/project.pbxproj @@ -7,1939 +7,3827 @@ objects = { /* Begin PBXAggregateTarget section */ - 225EC5F2F324BAAC968D55C764D70D1E /* SwiftGen */ = { + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */ = { isa = PBXAggregateTarget; - buildConfigurationList = B21E9464DC37774B2AF91DCB9DDC930D /* Build configuration list for PBXAggregateTarget "SwiftGen" */; + buildConfigurationList = 0BD4EFF72DD4194F3E6290A1EAE82CBC /* Build configuration list for PBXAggregateTarget "Firebase" */; buildPhases = ( ); dependencies = ( + FB6BFA54D8E0043795CCFBF57526DAC9 /* PBXTargetDependency */, + B246D60A4784E7242E6F9573F6581752 /* PBXTargetDependency */, + 0C26C138EB21155893EB3AAE8342452D /* PBXTargetDependency */, ); - name = SwiftGen; + name = Firebase; }; - 56C65DE44367A2F21D49CA08AFC9FB3B /* Crashlytics */ = { + 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */ = { isa = PBXAggregateTarget; - buildConfigurationList = A2C2BA6807BBA455470E664F6B40CF02 /* Build configuration list for PBXAggregateTarget "Crashlytics" */; + buildConfigurationList = 14608CC6B8CF27B7AF9B3D5F5B6F8607 /* Build configuration list for PBXAggregateTarget "SwiftGen" */; buildPhases = ( ); dependencies = ( - C9EE7669C499C214D32673DA70F448B1 /* PBXTargetDependency */, ); - name = Crashlytics; + name = SwiftGen; }; - 5727E61F2F741F9002936940674C2C4C /* Instabug */ = { + 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */ = { isa = PBXAggregateTarget; - buildConfigurationList = B7E7737163084DF0736A1DA737474EA7 /* Build configuration list for PBXAggregateTarget "Instabug" */; + buildConfigurationList = B345AD1AAB27ADDC33CD59391F2A2578 /* Build configuration list for PBXAggregateTarget "Sourcery" */; buildPhases = ( ); dependencies = ( ); - name = Instabug; + name = Sourcery; }; - 9297674709A684A35778E46A8DD2FBF1 /* SwiftLint */ = { + 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */ = { isa = PBXAggregateTarget; - buildConfigurationList = 08E73384D62CB365E65493BF13FCEBF2 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildConfigurationList = 0A1FEBE926726C9A3E064BDC1F0E7D33 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; buildPhases = ( ); dependencies = ( ); name = SwiftLint; }; - B3D97E5DFD9D826348C9FD6225F76AC7 /* Sourcery */ = { + A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */ = { isa = PBXAggregateTarget; - buildConfigurationList = 1DC2CF1023FFA0AB7BB266205EFFB20A /* Build configuration list for PBXAggregateTarget "Sourcery" */; + buildConfigurationList = EF7E77D70CE9CA6FA1C9D136EC7A4F62 /* Build configuration list for PBXAggregateTarget "AppCenter" */; buildPhases = ( ); dependencies = ( + BC9C5B4317B57C84FDC286747A6C68CD /* PBXTargetDependency */, ); - name = Sourcery; + name = AppCenter; }; - DACB20301113D16B776F458649C04D75 /* GoogleAnalytics */ = { + ABB048B191245233986A7CD75FE412A5 /* Fabric */ = { isa = PBXAggregateTarget; - buildConfigurationList = 53C2FC4108B64D3730F1FDD3C9662622 /* Build configuration list for PBXAggregateTarget "GoogleAnalytics" */; + buildConfigurationList = 44BF99169533508633331B4E79AD527F /* Build configuration list for PBXAggregateTarget "Fabric" */; buildPhases = ( ); dependencies = ( ); - name = GoogleAnalytics; + name = Fabric; }; - E28CCDDA0BCE0276CB18E6AE6E42CC00 /* Fabric */ = { + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */ = { isa = PBXAggregateTarget; - buildConfigurationList = 44BF99169533508633331B4E79AD527F /* Build configuration list for PBXAggregateTarget "Fabric" */; + buildConfigurationList = 615A1A40348710AE156325FFE219FE30 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */; buildPhases = ( ); dependencies = ( + CCB4B2FB4874EF61E26C0C42BF0A95E6 /* PBXTargetDependency */, + 73A206221EDC7792C0724E183F29C491 /* PBXTargetDependency */, ); - name = Fabric; + name = GoogleAppMeasurement; + }; + B593490A33943610DC035C394E10D07A /* Instabug */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B7E7737163084DF0736A1DA737474EA7 /* Build configuration list for PBXAggregateTarget "Instabug" */; + buildPhases = ( + ); + dependencies = ( + ); + name = Instabug; + }; + C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A2C2BA6807BBA455470E664F6B40CF02 /* Build configuration list for PBXAggregateTarget "Crashlytics" */; + buildPhases = ( + ); + dependencies = ( + C9EE7669C499C214D32673DA70F448B1 /* PBXTargetDependency */, + ); + name = Crashlytics; + }; + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 991E43F74ED979CF133D44C61CD0896E /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */; + buildPhases = ( + ); + dependencies = ( + 3792EB87049BCC72EB8B88E35FC33ADB /* PBXTargetDependency */, + DC9B574DFA929B605978935F3BDB7CD8 /* PBXTargetDependency */, + B59975B1711C1B93F51408259602A32F /* PBXTargetDependency */, + B5290BC5AF5A74B7D2919728FDE4472E /* PBXTargetDependency */, + E1D1984FE10DD52FB5F2B2F12B34CD23 /* PBXTargetDependency */, + ); + name = FirebaseAnalytics; + }; + D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 590CEAC43BDDFAA9598150F9D23A62A1 /* Build configuration list for PBXAggregateTarget "FirebaseAnalyticsInterop" */; + buildPhases = ( + ); + dependencies = ( + ); + name = FirebaseAnalyticsInterop; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 01C5D6067D7B2D44FEBF1E50F5A5E59E /* AcknowledgementsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C2A42E80DFA41030FABD4A88393F4D /* AcknowledgementsListViewModel.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 029DA4D76E0757FE5918A60D5B6617B7 /* Special.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CCAE7D4A6245F5F4C44F739DBC1DE61 /* Special.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 043BFE345DC1FEA899CA430F42BBFBFD /* NavTitleTransitionBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3639D14F3C07D749FB3063E068487445 /* NavTitleTransitionBehavior.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0441B2B52D9803F39A5D26222BDDFE26 /* UIImage+Tinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E41B0F9E8C162A676783159D2E6BB11 /* UIImage+Tinting.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 048CB1CF7A0E7475798E5CC6EB5FE200 /* SDStatusBarOverriderPost8_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4CA57B497201B0B30CAB96DDE10D16 /* SDStatusBarOverriderPost8_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 061A426D3F457E6D0A052767C3F95076 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - 06F4ABBA147243A15DD55ED5F8E27843 /* SessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3E0BA8DC4603ECFD3151F8B3C81598 /* SessionManager.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 096B17211F37574FE3BFAF2ACD91D703 /* TableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B116AABF6F54A2E56D0AA81C893247 /* TableSection.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0A33AECCF24B7B360AD0753C85DDC0BE /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4096AE254E9EB97D97FD6EB20D605B6A /* ServerTrustPolicy.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0AA01A8D182D97EF8EFC886C90F4F047 /* CubicBezier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B9CD9D4507F0BB5DA2B05A298D3C3AC /* CubicBezier.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0B8D46B2C05CCF70B33086EDCB861DE7 /* Anchorage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B576D87C99AA3051DC9EFE733505C01B /* Anchorage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0BFC7647D9C51B1E74751697F1CD06C5 /* SDStatusBarManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C615B52490F87ADAB2878CBBA62A49EE /* SDStatusBarManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0E272B4F8155B0641E90276663DFBC56 /* OHHTTPStubsResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = AD4EA92B56734A8CA71BFB65EC5996C7 /* OHHTTPStubsResponse.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0E3542A5A5F3F9EFA839EDC77195B2CB /* SDStatusBarOverriderPost10_3.m in Sources */ = {isa = PBXBuildFile; fileRef = B68AFDFA486327E986AA02A5299A8997 /* SDStatusBarOverriderPost10_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0E793EBB5C54DBCA6680965E88D45D83 /* SDStatusBarOverriderPost10_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 169E0A2C66830CE4D025F55BF0B70D78 /* SDStatusBarOverriderPost10_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0FA7AA39E8C2A567206C8834E3F39F95 /* HairlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0344F233E115ED3F7D904DC23394C60C /* HairlineView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 101E6E896AA3A2A7204E96871FA5BB4B /* OHPathHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C90242292A7BE097ED8F53F6314A670 /* OHPathHelpers.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 12A66D2C67F417928A30B4937F2704C8 /* Alamofire-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E37EC6963507772140141310564C96A7 /* Alamofire-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 163787FC8590421DC1AAA972E17D7C07 /* SimulatorStatusMagic-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BC96213BE7B62B82294197DF2AC70DA8 /* SimulatorStatusMagic-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1A8A306730B51E42994048E5BAC869B6 /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7268C56B15EE03AC9317CFB3648AE37 /* DispatchQueue+Alamofire.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1B57410364091178645D752CFB7D5F0E /* BetterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47CB2C8C52E2A4F6F847C2D4939E36B1 /* BetterButton.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1DE5C075140703A862F18A6426944EC2 /* BonMot-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C580B89A921E19C037BD54E71FF73A6A /* BonMot-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 23102CFEC4388DD74DA5B4EC0A55681E /* SDStatusBarOverriderPost10_3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9E56C55E5C3E4C28EBF213499DC13B2 /* SDStatusBarOverriderPost10_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 244629EE4387C24F47B469D962A9F30D /* CGFloat+DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427306A6F25ED154EDC741171B0672D /* CGFloat+DeviceSize.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2593D80AA46FBA1605886C6122935880 /* SDStatusBarOverriderPre8_3.h in Headers */ = {isa = PBXBuildFile; fileRef = DFA0BCDC716C3C2DF6E46612791CA5FD /* SDStatusBarOverriderPre8_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 25C1218514FAF0A2B59655537CEB164F /* StringStyle+Part.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712AA0B3114BE06914AA73650935B4B3 /* StringStyle+Part.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2660387952A6E58B87D43CD72F36967F /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54C8E02EC8ABE5CF2CA2B3840F75FC8F /* AboutView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 276F0DB6CC331B0F3C7839A3DD151CF0 /* SDStatusBarOverriderPost9_3.m in Sources */ = {isa = PBXBuildFile; fileRef = C3BD4ED7910EC78F54E9906021EAC11E /* SDStatusBarOverriderPost9_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 283F3373EAC068D98EA40E496B066D33 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412B8AA2EB07D89E85469CB8B5773CC3 /* Result.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2B584F0C7B5B845770993315171F672E /* Compatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CA678F606DD3E9ABC1DBDF7400C03B2 /* Compatibility.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2CFABA81D7B9737E055D2B7EEF203830 /* AcknowledgementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB51FACE363CF08AD66B491366ECCA6 /* AcknowledgementViewController.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2D80427789ACD436DB938223E2268014 /* OHHTTPStubs-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D1715D98301B1F97137AD0E551489F6C /* OHHTTPStubs-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3199D76F19D7E097659AA1276AE81547 /* CurveProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3749D57AF44719F99E7573D0EF50F406 /* CurveProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 351ED3D4D7BB19C3AA1A6B40D6C55A54 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B921E0CBB6CCB74325890A14EE6C3F5B /* AppInfo.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 35A3E179FD493A9B73FFDF67193C0CF9 /* FormattedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90A96D40B7CB86171BF8078F9CA3D9A /* FormattedTextField.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 36A17844B7FA84C2DAA92E9C815F3A9D /* Tab+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD288A8A84E421BED98CFA78BA83CAD /* Tab+Adaptive.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 36C99CC230B66FCBE3873860A22742F9 /* NSURLRequest+HTTPBodyTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = C7ADD80B33BD1D3965F9685D011E653B /* NSURLRequest+HTTPBodyTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 372D97CF7CC4E40E263C09B1FBC6C4CF /* Anchorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA5E72258FCCDB8B342B3D19FF405C /* Anchorage.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 39245329F82BE79E611D9375DC1E3FDC /* AcknowledgementsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62AF34195393D64764BB5AE60633CF06 /* AcknowledgementsListViewController.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 39ACCBA64C7A35BCF9C54D0FEE8462FD /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B61F355D3DB41F42478FC6C1F38A450 /* MultipartFormData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 3C683D8D80512159018867E961184EE6 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF48041B0643C6B8315D6381008DEE3C /* SessionDelegate.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 3D793A93993A3FEADF5BDF9CF03A365D /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 673ABFE194DF7A08FA263E12BAB82F4C /* Alamofire.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 3E7EF4E43CDFF20CF7029E27C84BDB71 /* Compatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA525AAB4893235D02EA212CA8407AE /* Compatibility.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 3ECC0BDB6024D4967CED3A751D138ACB /* StyleableUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 362EF0199AD907539D86EBEF1DE6556C /* StyleableUIElement.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 492774AF8B865F9BC7209B3B3B258A51 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7BCF16E3577A7314986934680E4C23 /* Response.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4B02D5480199C26BA2064D60AA872852 /* LicenseFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70668D84A9B3C780A359D0F2B58A1D4B /* LicenseFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4B72D0B7634016622F476687729A18C8 /* KeychainAccess-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A80FB9309074DE8E3648C328313041C2 /* KeychainAccess-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4BEF783784501D68A58DD7A06AE52D8F /* Priority.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78D61CCC7F7CA3A111C6C359B619EFD6 /* Priority.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4CA5BFEEC04C9A430BD5E4F74C7F555A /* OHHTTPStubsMethodSwizzling.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B2E6AF6F88FDD1CE6C631AD781A61C9 /* OHHTTPStubsMethodSwizzling.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4D3096DD0BBDA7375893340174F31077 /* TintedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171475FCE61CF50AA00728DC54688438 /* TintedButton.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 50A0742CD908C7D183E4FE3209DA3F66 /* StringStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E6EDD19D24D9E3522A79BF5F36D8F2 /* StringStyle.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5166782BDE710463669B746ED5D25342 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72B5BB3EED5E5C863F41621DD901083C /* Protocols.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5180B11F592D4E2930C91059A8A0FB21 /* AdaptiveStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC14BE78C6ADC4A456ED440DA669B424 /* AdaptiveStyle.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 51AEC9EDBD8252C6ECEC8264217060CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - 524F2E454EE4A68AC394CB3B4E77EC79 /* SimulatorStatusMagic-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1965AF062F89C7BDA3AE35620B5182 /* SimulatorStatusMagic-dummy.m */; }; - 53C5CC3A1581C23558F75CB3C255AC24 /* OHHTTPStubs.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FA9640C042660F51CFBC1B9D754150A /* OHHTTPStubs.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 54C8E467F3E3EF20E3896D98AB5E6551 /* TaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB96B984A6D557536E37D38A9C71887F /* TaskDelegate.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 55FBD894BA4FD15AAA7C9ACAD7EC3794 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CEC4C18F7EF40BF8EF7C4EA61392DB /* Notifications.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5655EFB774E324469A09273B1512314D /* OHHTTPStubsResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = A71071A87AEBBA036F448F39A4AF7226 /* OHHTTPStubsResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 56A41DC485A066C2F2CB120BCF3B3984 /* SDStatusBarOverriderPost12_0.m in Sources */ = {isa = PBXBuildFile; fileRef = 61D71EA297A255FC6751524FC2D7AE30 /* SDStatusBarOverriderPost12_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 57A3D7ACFA17C58BECAFF57D63FC3E27 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFD134FCA91FFE97E31F5E29CF515503 /* Log.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 594443AA4A95549682AB9748FE426BBF /* FontInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11D7CFFD8553B55C3A3B2272283373A6 /* FontInspector.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 59E5F1CE40CED4315B46012E19E626FA /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39279866EC1760AFEE29D2DEEED6C856 /* ResponseSerialization.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5ABBBE4762B96BA1E1CB6377EE44AEEA /* Clamping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694AD7393AED493BB49E808D261B32A7 /* Clamping.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5AFEA52EAFD86CF5A2CBF287BBBE5F19 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80930814506B3CE5606AA7DED6CBA9B4 /* GradientView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5EC9BE209594B8CEF714DF3344B2698E /* UIView+Lookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9B5EA89BF66F54C9437D2204EC0D69 /* UIView+Lookup.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 60438F5AF861DD37067600E5638048B2 /* OHHTTPStubsMethodSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C509062B34F03EFFC01A0972C94C56B /* OHHTTPStubsMethodSwizzling.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 63DFF8A1ABBC620D17234C62E5F8100F /* Pods-PRODUCTNAME-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FD33C68E323DA2EF0D6FAE8737B0BD1D /* Pods-PRODUCTNAME-dummy.m */; }; - 65D81884C107EC21BBB727B057A9600F /* SDStatusBarOverriderPost9_0.h in Headers */ = {isa = PBXBuildFile; fileRef = D8D0E31FC29539DB63B7901E4B473483 /* SDStatusBarOverriderPost9_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 661122C9F59ACA33B5D6B98BA70DB455 /* FontFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F12A1D968B46216AE4EE506629B554E /* FontFeatures.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 672BA36C53C17E2F3833937232EDCEF4 /* Shapes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97594C320B5EFC4497444BB58291142A /* Shapes.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 677CB0F83DF25BB8756BA7CBCD539150 /* UITableView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECFB2D89D8B3332F5F17C1CE83D7E8F /* UITableView+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 67C20222D613F76731013C8B7C0A3CF8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - 680B1E03B052C11DE3E6ABC9A5387F8F /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5086A712A691195906CCBD885DAF44FB /* Timeline.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6A6A63FFC93F55AC483492B8FFEAC07E /* OHPathHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = BEED7AEAC6B377BEABA32BCA6E029D06 /* OHPathHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6AC5E3D32E8EDDC9D4FABDCF58C9668C /* TailoredSwiftTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB6C041C62D7A0FC5904F4CA72030FC3 /* TailoredSwiftTextView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6C87908248F80080D6B25071845FF921 /* Emphasis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89450B8529A81C5B1E75A786D5FABC3D /* Emphasis.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6F449D963205D988420656C9AD1F5A17 /* AttributedStringTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704ACC5578BE8DC6950CC29EA7C1AFE1 /* AttributedStringTransformation.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6F4A5C7A58D039539FF8D80FB810C8BD /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A1F76AAB60389D3C093AC1A50BF0A9 /* Platform.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 71CF94946674B5B6A64C4CE9B8E34B38 /* NSLayoutAnchor+MultiplierConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1AF230CF867C88C770CE9C374EA4A9 /* NSLayoutAnchor+MultiplierConstraints.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 71FC49E73C6EAFD50619705CDE7F2CEC /* NavBarHairlineFadeBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 276D6C93C6813A9140365BF3CBD94A65 /* NavBarHairlineFadeBehavior.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 73A4E3A002698D9BED81D3C7E2834222 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42BE2BD8793574C8CCFF047DE230880 /* AFError.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 749AF41B7BBF16638E09E26348C7282E /* SDStatusBarOverriderPost12_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 76574677F65789134324FB1D3C925091 /* SDStatusBarOverriderPost12_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 76042774D794C5BA362A7CC2C6D3035D /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0003595E56E3351A484C39D062FAA5 /* ParameterEncoding.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 7743E8AE9F8A25C9499A2CC8F5B73D58 /* NamedStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FABFF9927EB4903E6F34356FF106F4 /* NamedStyles.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 7E465108E9D1294F543867B1C55C3C3F /* AccessibilityHeadingLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0E7C617CC610A75A05A76F56C75DB0 /* AccessibilityHeadingLevel.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 7EB9B575E1B2B22C9D11A03AEEF214C4 /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F23572C7CB158962AEB29506087D42A /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 81F19671CAE82B5B880CB1DEAA9FA08E /* OHHTTPStubsResponse+JSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B709879A680D555D406FEF46B4B386 /* OHHTTPStubsResponse+JSON.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 869932972E5299B14D33EE967983B017 /* ContextualAlternates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08B38982F150A6862B8AD2A945D9B407 /* ContextualAlternates.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 8A4DD3373E0DABD27F453492DC72B098 /* NSAttributedString+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF1BC0A1B0C287F0903058BAEC132BEA /* NSAttributedString+Adaptive.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 8CD59949C6FC86186476CE9430AD6E3C /* OHHTTPStubsResponse+JSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 8322C8C3CC5229674C4860D5DADC299F /* OHHTTPStubsResponse+JSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8ED42B59366DC0A373B2B2BF5AE77EAE /* AnchorGroupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6850346376F7BEE1EB250B890DCBE0BF /* AnchorGroupProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 8F77E3B7725FBE51D242BC570B80850E /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FB8C1752861586CF1E04E22B05009B9 /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m */; }; - 8F94A3B78C0028C3506E5D9450AE1208 /* SDStatusBarOverriderPost10_0.m in Sources */ = {isa = PBXBuildFile; fileRef = A6A3C66135761B8589F2EEC25372EA62 /* SDStatusBarOverriderPost10_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 902BE41A1CD1EC0BDA233DF4CADB93C1 /* Pods-Services-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B897A3FA47CC0821B4DB6D3C2B7E99CB /* Pods-Services-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9042046A3B8AFC4F7BB5C3D3492BEBB4 /* SDStatusBarOverriderPre8_3.m in Sources */ = {isa = PBXBuildFile; fileRef = DFB0EC7EBB399F7D5A85850FD00CE2C4 /* SDStatusBarOverriderPre8_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 90739588523B5D65BC6CE9E4B0B1AC71 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - 9526DD29040EF10E2E637911921C947B /* NSAttributedString+BonMot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85A6A4A85CADB17311A03BB6003CDC8B /* NSAttributedString+BonMot.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 96043478FC52AE27B579B4D4C9BF7E27 /* OHHTTPStubs-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EB19F16C37CD2E91D6E593747C7AF54F /* OHHTTPStubs-dummy.m */; }; - 9A7534A4ABCC5B65D1D2D7CF5162E7F5 /* Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88E5F6A803FEFEF70F140D44D4DD1CA0 /* Transform.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9A8CBEDF59D32AFB564B78EC46995795 /* CoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC68423B5D03B01844BE44E57D3105DF /* CoreDataStack.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9BE56EBC243C1D6202F97AEC29730C84 /* Swiftilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 289F895A731229C94D7D07DFD3480E56 /* Swiftilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9BEBA94B220E19FF7106BB065A97676F /* FloatingPoint+Scale.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B35764F050EDE7B00132EF81A34F42 /* FloatingPoint+Scale.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9FAF65A3D649F0C41F77EBFC9F5D61E4 /* UIView+KeyboardLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16618C3BC05BC3E526CD791AA381BFB3 /* UIView+KeyboardLayoutGuide.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A0E3993EB2AE9B0327145EC4D40E37A7 /* ViewControllerLifecycleBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = C56086F41BE1C76C0A2162242BE882BB /* ViewControllerLifecycleBehavior.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A29D8AA89F0BF6B0871D213341DFC369 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBA24296CBFCC1AB1BC5AB37A4F7BD49 /* CFNetwork.framework */; }; - A3FA2D02F6245663982D02FF19F12CD0 /* UIViewController+Lifecycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0FA4328DAC940D1CB38E6FBC0DCDD6 /* UIViewController+Lifecycle.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A3FBBE9D11DBF5311AD8603A99AB803F /* Tracking+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 330CCA593DDAE935D8E8573A0728E931 /* Tracking+Adaptive.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A43B18898AA1BF4CEA7C52BE9422547E /* SDStatusBarOverriderPost9_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 54B8EFB70012E9BEFC2371D3FF24AB1E /* SDStatusBarOverriderPost9_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A5E2A433F778C80CB345B9E240FCFDA7 /* SDStatusBarOverriderPost11_0.m in Sources */ = {isa = PBXBuildFile; fileRef = BA2995A05285EE6DED3FEEA5F13AACF4 /* SDStatusBarOverriderPost11_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A8D5B034D56D54FC40D8F8F7CD25ADC1 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAAAC152788B64C89E923A18277EBA4C /* Request.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A93A28F9BE26581E436CFA6556F9F410 /* PlaceholderTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54CC3A9A9520AF155108F8CE284EB864 /* PlaceholderTextView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A97A129F12231CA847BF2A4DB012F98C /* IndexPath+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B23ECB1A1FC9AA01FEB7FABD6E284E1 /* IndexPath+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A97F384287EC736D01335030A60536E8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - A9F139BA8F48DB38532AAD38F6D5C669 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B67E5A3B83075128A1543C2893FF8978 /* CoreData.framework */; }; - AA31A382B39D9989B540D545D50B9364 /* TextAlignmentConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04FA80AC5B62CDAB5253E08409C0D0B9 /* TextAlignmentConstraint.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AC61ED443F5D8F217606A0A59673FEC4 /* DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6991AC15FB6E796C0D2D216AB1B409 /* DeviceSize.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AE53B6D903F4A5991226224B2AE27299 /* Pods-Services-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AB95055F14CE265D5FB56048A2E19D1 /* Pods-Services-dummy.m */; }; - B297DD032E18AAA57C8EAB9C413DF7A2 /* Tracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE8ACA571ED75517D0E41EB2D0AE086 /* Tracking.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B2F7BC03C3C341AF9E64A3C5687E2C46 /* CGSize+DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D90E1557A97E8534260AE63FB8122C2 /* CGSize+DeviceSize.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B634F8070A243AD9742E249A9806C63A /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A56048850B5EB8CF23F6DAD9C06FBF7 /* Keychain.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B66D7B67F588663DDCEF3033B05970CB /* MutableCopying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89E43AF1CEC2C19E8EB86AE3397389EA /* MutableCopying.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BA0D738F3F0717185AA235A506E574B1 /* AdaptiveStyleTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A72D85B745ED549CABA1B2596D6E07 /* AdaptiveStyleTransformation.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BB47B70BC730B4DF1A0047DB2AB1E3FF /* LifecycleBehaviorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A0C90ABF64C64D2F8388FD400A65C3 /* LifecycleBehaviorViewController.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BB6DA79029B5466E4636255DE6CFBE44 /* SDStatusBarOverriderPost9_0.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E460FE658668EC518CCCB65C4F75F33 /* SDStatusBarOverriderPost9_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BC58D547EF617D867B5C244231BC36C9 /* Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1ABD0449009E446A4D3F9A93FC4DEB /* Internal.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BD86B2C7553D3D4C26777144D81B0906 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E17F1FA7E71417208B484A6B4798DDD6 /* UIKit.framework */; }; - BF1D822FD50EB7F0312B9A6D5BAA2C67 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 287203EA6EB5EB516A7B9DE8645F0403 /* OHHTTPStubs+NSURLSessionConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BFAACF3BB3BA01515F386FB5784F868B /* UIKit+AdaptableTextContainerSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = D80B127AD7C7BB100CC551B493D3D794 /* UIKit+AdaptableTextContainerSupport.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C09E10BC1C5AE077CFE154E20C184CB7 /* DefaultBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E55C6090DEF8FF17C4877AB940FD591 /* DefaultBehaviors.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C1B3B07FC6902AD71A16B6D6206F7026 /* FieldValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81E944F8B0AEB55DC7130BCF5D0265E /* FieldValidator.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C29A2B46489E9CAC4B750124BC1EA2AD /* UIStackView+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 473B67F1C327A540855E3FC4CDFA3DEE /* UIStackView+Helpers.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C2FE21AE758AA4C15321D3C5597F4B99 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F338A55DD7E095C1009887CED6DC4AC /* MessageUI.framework */; }; - C4604B2C39F88DFED999470F29402851 /* SDStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 600A0B900A253A3C1175F9E4D95DB5D0 /* SDStatusBarManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C62B7807668EC142A9113D69D92FE0A8 /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6F2B0D3C4AE001AA8D39C968195273A /* NetworkReachabilityManager.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C7AFE8108875A1E857C32C951C5F1410 /* OHHTTPStubsSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE18F1B83B66E2F8033DD4F4C792ED8A /* OHHTTPStubsSwift.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C883489560D63778318E2FD860326389 /* Compatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = AD5BD87CBD27D13BE3B64470D2514F3E /* Compatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C8A9F97A0CFBE7C804E7D5525954E6B1 /* SDStatusBarOverriderPost8_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 828C42D1340C4F63C8F0F9D333CD612A /* SDStatusBarOverriderPost8_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C9B487F21FE826E6875830363BC1ADE6 /* StylisticAlternates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 863B364319BA1C8E81DB7F006A9A31BC /* StylisticAlternates.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - CADCB575F61C052120F85B0856034D8A /* UIWindow+RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACA3A4AF812957B34242F8835CB3ECFB /* UIWindow+RootViewController.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - CB13CCC62B5572D173A5F3759E4F23BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - CD30777B323A5AC47CDCAB7FE59527F0 /* Compatability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9270993480FEDFD0F12D1749E45B20D3 /* Compatability.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D0E8FA0DE59D2EAFAEBDA5D0CB9B00F9 /* Pods-PRODUCTNAME-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FE233BF7FEEB9A8A795679328F0C82 /* Pods-PRODUCTNAME-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D159754F3CF9C87002B742E85D20CA02 /* FeedbackPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5B2FEF0A506CDAE2D10761BE2F376E /* FeedbackPresenter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D15BFCBBE9C1D555C15C2F363B1657D2 /* UIViewController+Deselection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5175D0955C66D6BC673461F540D755E6 /* UIViewController+Deselection.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D2813D340E46C0B4343AE0B994514703 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - D526BD492A6B5CD97BC93DF45FE859EA /* BonMot-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CACC82C9360F0099F26C79E3B2059185 /* BonMot-dummy.m */; }; - D5A93AC6B10C26F52943B5E8B28DAA0F /* Alamofire-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 957FC6AC38169C7173562AA6E6597C5A /* Alamofire-dummy.m */; }; - D6218875416D995A010F7D92463FDE49 /* XMLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5922604290D09B15C428A4127852F8D2 /* XMLBuilder.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D831E4DF2BCFDC9ACF0E15A1FE4366AC /* SDStatusBarOverrider.h in Headers */ = {isa = PBXBuildFile; fileRef = E74DC75AECA924D9AA03636808FE7BDF /* SDStatusBarOverrider.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D898348F4D8F2912DE123B843405205D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - D92DC1A062A72652A63758BEF8E3940A /* Anchorage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E340EC5B601C12215D9F8E375C37261 /* Anchorage-dummy.m */; }; - DC806AF439B1AB8881B705058EEDEC16 /* OHHTTPStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = 8616019682F89AF777F1467F9FADF221 /* OHHTTPStubs.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DDD1D058B27B2E4F223317D5E483465B /* NSURLRequest+HTTPBodyTesting.m in Sources */ = {isa = PBXBuildFile; fileRef = 0844167EF0604BA510C035ACDF453F20 /* NSURLRequest+HTTPBodyTesting.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - DF2657258D6ACA8933FB39795FEB0670 /* Ligatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90AC5B33AAA6EF1AB9164725FFA0B6C3 /* Ligatures.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E0AAFD9138FBBC64CA5E5D1DB1448FD7 /* SDStatusBarOverriderPost11_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ACDCF9FDA55A7DB7730D6DB537616F6 /* SDStatusBarOverriderPost11_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E157626B0F43C831B36DF163D864E02F /* Swiftilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 423575D637674B034C086A88A750516A /* Swiftilities-dummy.m */; }; - E418D809C96FE15438768EBA32073EB4 /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45DE58670D5CC4C511D327BD0944AA59 /* Tab.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E46129D5E43637E7B0711552796A944C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - E530D1A57C985798CF27D8ACDF195330 /* Image+Tinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08FEAA71D51B643545C21B77DC4D28DD /* Image+Tinting.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E576BAF7FCA60BDCEA9809F47DDA30FD /* AccessibilityHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB38C12AE406FDC85937CCF35845E787 /* AccessibilityHelpers.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E64A457BFF181C74C2ED4F46381479A2 /* EmbeddedTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24EBA9AD10434F4F0FA3C89E27567DDA /* EmbeddedTransformation.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E7D43FA3D083CD03552EEEB3FECFEB14 /* UIColor+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADA69A7B37937B271062924B815424C5 /* UIColor+Helpers.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E8943BFB483709F10502286E0FF9C218 /* Composable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095ABB58DBD99D3A10453F530368A5F0 /* Composable.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E9B689D5EA5275942FB3A8FAF46A234D /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2448D385AC85F37AF99BFC03ACAAB403 /* Validation.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - EF310CF64A4AB66DE85A0573C718E220 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E17F1FA7E71417208B484A6B4798DDD6 /* UIKit.framework */; }; - EFCC6D0B862525E3AE1DAC9598CAD0DA /* UITextView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBF2880E3762207FCA439FC5B3BFE9D1 /* UITextView+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F0A08B6F139854AB50C4AE7A32EEC7A1 /* UIKit+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA18D0EBAA000A7E08DB708924C2B9 /* UIKit+Helpers.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F1766890C65E010081DD7D41C2EF4098 /* Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA462C4F41ADFF2B1F485CA4D300A507 /* Keyboard.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F9683710500AF59F44487B5D62CB46A0 /* AdaptableTextContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DDEF6C866280C73475A52AC509488F /* AdaptableTextContainer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - FA16B3A8C9B5B395CC6DF41609CA4D6C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */; }; - FD6FA1376D516E7308815F44A97856D6 /* KeychainAccess-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E61565DBEC973F19175F0B6B4BF9251 /* KeychainAccess-dummy.m */; }; + 002B61DB441C6864402B2620001F2D24 /* Special.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E603AE6FAEA107641D9E8499AD28ACD /* Special.swift */; }; + 00615AAC8F76F88D5B261CDBAFFC42CC /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E893CE5D8A792CBF4C835E33C903AB37 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 00B3DFC8711DBA5BEFD89F179EFD44C1 /* AcknowledgementsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91A527A11C0F5C0E19DEF21E7B9C7F7E /* AcknowledgementsListViewController.swift */; }; + 0100B51AAD85D2A5B7C3725618933398 /* UIView+Lookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52569BDA16818151E3735016A95C16B /* UIView+Lookup.swift */; }; + 021DB76932CE50DD90304FEBFCA8BE77 /* FIRMMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = FDC9DBDC4B19FB33CDC14DE23114B21C /* FIRMMessageCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 028B2CECCB9AEA8424D7C00138A38431 /* NavTitleTransitionBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01502087710687B101E4DBC35B149B69 /* NavTitleTransitionBehavior.swift */; }; + 02FBDFBD52654C16E8616F45114FAA14 /* TailoredSwiftTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F7DFC7F79DE29AD380D6C23EF374F66 /* TailoredSwiftTextView.swift */; }; + 03EF25966CA31FFBC31B8044BBDB7C78 /* FIRMessagingCheckinService.h in Headers */ = {isa = PBXBuildFile; fileRef = 7930F6E4B1DBA1F8B3A51893DC47D6D9 /* FIRMessagingCheckinService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 040519868B2FE15E71CE862276B5FB0D /* Anchorage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 569222352AED8AA275E1295F319C179D /* Anchorage-dummy.m */; }; + 04EF7CA88D2E1D49B56D74409399559A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 059037195C74C676763DE7253C64DCAC /* FIRMessaging_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E5AF5D638A5E46AC1F536B0D9FC686E /* FIRMessaging_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 05A179D28D1AEFB2994F50DF04732ECC /* GULAppDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F492B106E8EB1E2C72059F4CEC2ADF4 /* GULAppDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 05EBDF811901C96CB4A388C239C95E5C /* pb.h in Headers */ = {isa = PBXBuildFile; fileRef = C146F3AD61FC35B7C5ACADB293B2E5CF /* pb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 06B290D6C5B112EC54DE4AAF0921A969 /* Compatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C88D2EB51952A1D85A0AB4AD8FE1D6 /* Compatibility.swift */; }; + 07004386F300F8DD87A2D100C010521B /* FIRInstanceIDCheckinStore.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6910A0DE802228534590DFC11D90C2 /* FIRInstanceIDCheckinStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 09BBB2DFD0CCA4F842ED217E1ADE6141 /* nanopb-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 22D8C3460BFD762A935246A9445DDDB6 /* nanopb-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 09F7DF5894417D5165C5B1873E46B448 /* FIROptions.h in Headers */ = {isa = PBXBuildFile; fileRef = D2B4AA2B21255F7A6AA09F0E059321BF /* FIROptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0AAA11C4CFB301157A24BF56A7C1ED7E /* GPBBootstrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 670326828280195E95A7805733428555 /* GPBBootstrap.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B9AC443AC8498AB675F72F8A84D961D /* CoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = A39DC1AB08D7C48D33B0213FC070EE91 /* CoreDataStack.swift */; }; + 0C0BF1B04934ADA346E62844B9324E2A /* GULOriginalIMPConvenienceMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 6407CC37ECE767179AE4ED00301D5C52 /* GULOriginalIMPConvenienceMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C9D3548AB6302BFF4E52AB249E9B2FA /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C395986E3E5F5139E1E2D48B13C6B14A /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0D110E5F8DB3A38046128C3AD51467AC /* FIRMessagingSecureSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 37E010E6C2F14B116AD0A6E40D547F39 /* FIRMessagingSecureSocket.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0D9138EF60798B8D013C354FFC3F956C /* GULLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 319AFABD7CD5670EEEE2D2BA15A360BD /* GULLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0E47DE1D5D4C7AA8034D1B7F63774BF0 /* FIRInstanceIDTokenDeleteOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = B94ED403343770A491208CD276342FF7 /* FIRInstanceIDTokenDeleteOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0F8CD4F146F1C58231026AAF09FAC5EE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 0FD7700F7E5A81A21AEB14558CCCD67B /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FC123B26387B1A38B1AAB531554C64E /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1011297752537301D863BE2D4B01E43A /* OHHTTPStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = DB5BD78F6D7A28ACB840F946DCBA826F /* OHHTTPStubs.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 10239177A8AE0CD597F3FDCCDAC21FFE /* fr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 829D6EBA77079A9CFF95E76253E1B175 /* fr.lproj */; }; + 1077DE8C92C90C40F4D8ECE47B48EDB8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 111E7E93B775DC49472ABF1CDC8BD6C7 /* FIRBundleUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 367F00084F5782810F06E3AE60988239 /* FIRBundleUtil.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1168EAF844C5167A969F992B39124E95 /* FIRInstanceIDUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = A3AA81B96ABF2101A80128229B5253C0 /* FIRInstanceIDUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 12C27A0E31DE9B1B0B5E54C2C429BD54 /* GPBWellKnownTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 258251CAB54F309E8E640653850C4B32 /* GPBWellKnownTypes.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 130BCF85E0BDD69B046F3000354BA0B1 /* FIRInstanceIDCheckinService.h in Headers */ = {isa = PBXBuildFile; fileRef = 5215C876BC30D194764B41B21031B21F /* FIRInstanceIDCheckinService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 133BA9EE26B755C23B694417B33A6936 /* FormattedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F85F03D3204EDFA79866F18C991616C /* FormattedTextField.swift */; }; + 13818F8210CF5628758D110549396C75 /* NSLayoutAnchor+MultiplierConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2F76C4975A9F75ECFED7459246BDCE /* NSLayoutAnchor+MultiplierConstraints.swift */; }; + 148F3B7A2FF4E9CAC78C9E5AB0286CBB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCE4EFC833EB090ACE8EAA95D8F1FB5D /* SystemConfiguration.framework */; }; + 1735E3217A03B5B4EEFF084033ABE1DD /* FIRMessagingRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = E3AE805A7D220717142177291A6563DD /* FIRMessagingRegistrar.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 17CA76C0BACF692C96BD0A789D76C08D /* FIRMessagingPubSub.h in Headers */ = {isa = PBXBuildFile; fileRef = 7798FFAA50C6E5C495F258D8A51AFCF9 /* FIRMessagingPubSub.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 18104AFA575A3CFB614915516FA8A1EF /* GULSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = A668229ECF671E377647F4DE649FE2D9 /* GULSwizzler.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1931E725A11B3C13986AB78A8130111C /* NSError+FIRMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E51F53C43C26EC84AD204A2DF58797C /* NSError+FIRMessaging.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1A0898925095DFC70512C1A28BD9F587 /* Type.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 05E39D129D919E418F8D526AC9591021 /* Type.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1A57D555A841083C708009478DC31FB5 /* GULNetworkURLSession.m in Sources */ = {isa = PBXBuildFile; fileRef = F6B71CAF2E55E96D2C79702EA17AC62E /* GULNetworkURLSession.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B586862269C42A863000C3B70991A0B /* GULNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = E73E251E3CF96E1495BE3EC085526D94 /* GULNSData+zlib.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B5BAD2AE0BDB78D1797A3F079F2DB27 /* FIRErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = AC024504A5C4B47AE13B434EA483D427 /* FIRErrors.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B8BC5D48142213B30D7DB0D0B067738 /* FIRMessagingContextManagerService.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C651771BDA251122C0517F98DD229C4 /* FIRMessagingContextManagerService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B9376E58DD7B9226E8EBA79391DF110 /* GPBRootObject_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EE85328C2AA2BE65AC5476B9A3A4B9A /* GPBRootObject_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1BCC66B692E9EDE5C903B4469B4BCE57 /* SDStatusBarOverriderPost11_0.h in Headers */ = {isa = PBXBuildFile; fileRef = ECE318A98BEDBC9D92401EFDAE6EAC84 /* SDStatusBarOverriderPost11_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1BE02480F93F6FEF703BC98F779A8FBE /* GPBCodedOutputStream_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1064EA2176F4289B3F2DC02849A83825 /* GPBCodedOutputStream_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1C202B0C77A04F7D0E65F399808DBB11 /* FIRComponentContainerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E4A10F6099BBA9290EDF1F50E4E1E06 /* FIRComponentContainerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1C3586AF524004892635EFD9A2F411EC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */; }; + 1CD0155BAAB0AF2CAB66FF0A801DD974 /* AccessibilityHeadingLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9B9847934B602C43CAC9AE7E2EBD36 /* AccessibilityHeadingLevel.swift */; }; + 1E460A03738161788BA4D0258D3C2657 /* AdaptableTextContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF9BA9F1FCE9E687C9236562D28FBBF6 /* AdaptableTextContainer.swift */; }; + 1E84D4A521B67526F319DBFFCE9486B7 /* GPBUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C5A26153063FDC9CF29CACEBFDCE19B /* GPBUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F680A61812FACE2D5115195328CA3DF /* NSError+FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EB8515E357A8EA23661EBCD579561C3 /* NSError+FIRInstanceID.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1FA20690DF9A5043204742E88A203343 /* StringStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 786594362231C88055784CE1F30F160D /* StringStyle.swift */; }; + 203BE416FA99DFA5A8A48CBFD3D12D1D /* FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = C513955DA0F2FA1EC966C5DCB86267DE /* FIRInstanceID.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 220FF13741674D3D3CF5BAD8DFCE5E92 /* FIRMessagingPendingTopicsList.h in Headers */ = {isa = PBXBuildFile; fileRef = 662B607559C369907018526CD34E7A82 /* FIRMessagingPendingTopicsList.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 23A2410F3C4DE63B77014C9DE596F51C /* FIRMessagingTopicsCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 623AE596A3622CB246F0C91BF962A5EA /* FIRMessagingTopicsCommon.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 23B15157951EFE8223491E517FB38492 /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 78082F41A23883083EE4061BFC18A4D3 /* FIRErrors.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2612E406DE2FDD81958D99713579DFE4 /* FIRComponentContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CF43C772DF570A45DC9831438386FF8 /* FIRComponentContainer.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2646BB4FDA2D1690D9DA61405740F25C /* FirebaseMessaging-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F16A3F715737A448BD6736FC7CE8C23 /* FirebaseMessaging-dummy.m */; }; + 26939CAD52ABAD1A55806F176550DA26 /* FIRInstanceIDKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = DB6E2DA2A7458E3619DF8D70A1EE9011 /* FIRInstanceIDKeychain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 27168CA32C4871EEE4C1CE2D5909485F /* MutableCopying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 793A451BCFED3B0D33EF91ABA0E76DC0 /* MutableCopying.swift */; }; + 2723FECBFB4E4EE1EC645516FBB232D4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 27A8DB4EE609E1FABE7EA7835B6FF28B /* FIRMessagingInternalUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 29977CBD0F0F1352A376A22E58D14F56 /* FIRMessagingInternalUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 28292C6F27C2567FFD9A0C3130CFC626 /* ViewControllerLifecycleBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D70F6C27F2262A020CDFA6DBA6E0A95 /* ViewControllerLifecycleBehavior.swift */; }; + 28501C3F19644C8E8888E168B5163A2B /* FIRInstanceIDAuthService.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B76802A61020D8F2FF87DBC22F95501 /* FIRInstanceIDAuthService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 29D8A0E1833835AE95BB8D68783E01D3 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C494458D65556B106276B45877C5407 /* FIRLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 29F77423AD4D91EA6AA353C23B5C80FA /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = B53967F27884E26D24DE4B390642290C /* Duration.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2A06EC8F16F9A176A6E8969AEFCF557E /* FIRConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = B5391DB5CF7FE004619D4F1920521EA2 /* FIRConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2A81ADD3C0C26EEFD1409AD35142E0AF /* Pods-Services-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 43F95FB28B3B3DDC58B3E70C591BD759 /* Pods-Services-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2AA0A2B7267E8E75525D003D9A96E6ED /* FIRMessagingRmq2PersistentStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 846244C0EC47A8A7BE9B1E2506F77C50 /* FIRMessagingRmq2PersistentStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B088D091DA7DA702E17C2022DFE2D14 /* FIRInstanceIDTokenInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AC714289EA97E67199CA997655EAF27 /* FIRInstanceIDTokenInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B6BD33D9BA13D63533BF7A016186C63 /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B9F61513C3569FB8F5F80587BD0802 /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2BC2424190D3B6288B51C3DAAC70FE0D /* FIRMessagingCodedInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = FB1B0B49E7137AD9BBD29842C2A3A7BD /* FIRMessagingCodedInputStream.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2BD4A62FFC2595A77CF36ECD209FAC2C /* UIKit+AdaptableTextContainerSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D4DE2FA59344D4592D75A8D5A4137CE /* UIKit+AdaptableTextContainerSupport.swift */; }; + 2BF26FA6F5CA189C337AD83F534BC3D7 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0613D7FC4E5B1B63B0C08F9883F7B6CB /* Timeline.swift */; }; + 2D409981B90BFACE059F7069003F5372 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D7EE49F14DA03DC27AA4631DE48483 /* Result.swift */; }; + 2DF1DEC33EB066E5581440CD6998386C /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 72AA8EF20A9E0ED207B17A82A67948D7 /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2E5638B808692AE3B2213A66E618B793 /* GULNetworkConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 9221AE50CB51C7E8CD93A956CC3EA7C2 /* GULNetworkConstants.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2EF7C4DD8AE3B593B8DF4E2935543F45 /* NSAttributedString+BonMot.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA27AEAA510EE20594C0FCF896C53040 /* NSAttributedString+BonMot.swift */; }; + 2FE5FAA4B2358E5E17D36BDB048F9160 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1248BFF6EDD2B0B1963D8E18335E0DCD /* SessionDelegate.swift */; }; + 307995802DBDCAE24CD40AA467DFDD9D /* Swiftilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 88F89AA47577A480D576C38E3EDFADAA /* Swiftilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 31F595EB1AE5D570993770123D9A2A5B /* Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7558233F38BB01572FA6F6C87087DE05 /* Keyboard.swift */; }; + 3200DB013281B43E28A5C67E98EDCF1B /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = ADB4B0347B4897392B2245F4E44D0AC1 /* GPBArray.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 322D81E9DF88D46A7F0B60EF4B7CB1CA /* SDStatusBarOverriderPost11_0.m in Sources */ = {isa = PBXBuildFile; fileRef = AD72DEE352EC54E08A0DDA10EEDB3D49 /* SDStatusBarOverriderPost11_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 33108ECB357D1206B36ED2F85AC12269 /* GPBWellKnownTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 20D53BC1D9D046786E39FFC97B7B43A7 /* GPBWellKnownTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3322584F7CF6DD027B79F6BCA4651CA1 /* FIRComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 900494C92D1BC8DD44B41A1E185446A2 /* FIRComponent.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 337AF23300B055F9D0AF0BB5AC2F55E9 /* UIStackView+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5A2D89B160FEBC3EA6D9A26612606E7 /* UIStackView+Helpers.swift */; }; + 33C1DC1D1DBDCCD13C278B789AC82B0F /* Pods-PRODUCTNAME-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A572C6721447ABE0F589A4004BA6EFA /* Pods-PRODUCTNAME-dummy.m */; }; + 34F9A43BEE167441599A1035E0C14F96 /* Anchorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13FC2F155F0438B5C95978061F39743F /* Anchorage.swift */; }; + 35E679A58A9EF087D8AAFB484914B64E /* GPBUnknownFieldSet.h in Headers */ = {isa = PBXBuildFile; fileRef = B7B04D349B7F6EF4AB5D84952D2A53DE /* GPBUnknownFieldSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 360522FAF4C83FF5BB33C984F4D293B5 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 994790A4BDFB35C5FEEEB4B16ACD0073 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 365196A7B4EE1C83C432D345AA839C88 /* GPBDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = F33A6CC0B7DD266D5F442790D44ACD25 /* GPBDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3684FB4C4B318425C246914FE763A0CC /* TaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 548F85D6FB2D9B296B3CB2FD0B313CDC /* TaskDelegate.swift */; }; + 36D435F6F2D69F1A933BAE5D27B0EF85 /* GPBUnknownField_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DF285A229D15CB8F3DFBB3DD3DC7884 /* GPBUnknownField_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3864DBFDFD3CA45C50C5E35FED55D1C6 /* Protobuf-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D7500D2B23B7DC69CCA7B61577BEAD0D /* Protobuf-dummy.m */; }; + 39074F282BFA3893780C3F2330271BFA /* FIRInstanceIDCombinedHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 26880FF9FEB2270469CDC3F44CFC51BE /* FIRInstanceIDCombinedHandler.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3957709DBEF6C37401EF8F32B962985D /* AdaptiveStyleTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F95AA7ACDE907999406636AE9140BF79 /* AdaptiveStyleTransformation.swift */; }; + 398916FB2E858FCF90B787DF390F0646 /* FIRVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = D436B935FFA96DDB042376CB5C11E29E /* FIRVersion.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 39CE61B6B67AAA879293052A016A9B44 /* FIRMessagingVersionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C1809F979F3942E4C48A86D0F20B10B /* FIRMessagingVersionUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A1C7551BF0986016F6C2537B5E2733F /* FIRMessagingRmq2PersistentStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F13E67C41FD3508A00AC0A6F6CA8A43 /* FIRMessagingRmq2PersistentStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A6073E24514DD7FC8539E5C9BD6FF3F /* GULReachabilityChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E98DDB0684CD0EED258207851A2A13 /* GULReachabilityChecker.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A68C5510ECCCB664B640F57F86435D9 /* FIROptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 97EFF3947D869F0FC7D7D08A1B3B0A6E /* FIROptions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3AE9A26503715569C678C2C331591663 /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FE7B5BE33FDB3387A107014CDD4C22 /* Platform.swift */; }; + 3B17099ADDBF828A11994064917317EC /* SDStatusBarOverrider.h in Headers */ = {isa = PBXBuildFile; fileRef = ED9E474AFCCD58C67C788DC90A8A9AD0 /* SDStatusBarOverrider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3B8C1EA2A930ED9F1F28457FF7860F06 /* AcknowledgementsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D6419DC93CAC1E865DD9A730B5C8623 /* AcknowledgementsListViewModel.swift */; }; + 3D65EF2ED72527D8BD4359402DC8DE54 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD7A8A7135C2FC81974892005E66656 /* Response.swift */; }; + 3DA83DFE11641ABBF54EED0F6D91658C /* FIRInstanceIDKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = DB1194551671BF12886B8DECFEC28149 /* FIRInstanceIDKeychain.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3EA25AB8FC4048123BF2D50D8AEBEFA7 /* UITableView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 552F3B93D76BA12F543F0275D11FB3F6 /* UITableView+Extensions.swift */; }; + 3F318A17631E107812E804B75FFB7FA6 /* GPBProtocolBuffers_RuntimeSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FF4D0CB4786B5D9882E4D069869A3CF /* GPBProtocolBuffers_RuntimeSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 409D2E6AB1246D3B41550EC6F8B68695 /* FIRInstanceIDCombinedHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B49BB3E350F98DF8781264F7BB9D61B /* FIRInstanceIDCombinedHandler.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 40CAB5AAB5CF579001117DA2892ABA3B /* FIRInstanceIDTokenOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 08DA9B3BA661AA7124AE37AFA1396048 /* FIRInstanceIDTokenOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4137F7B8D747E67F776B744E4FF5A116 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED0360339FFD929C312164430AECEF5 /* Protocols.swift */; }; + 414165239CE300A52CEB93BE48E70607 /* GULLoggerCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D8C01D7DC37A7E86CB6EB912842D669 /* GULLoggerCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 41D8B6DE590FB9C57F9878F4A384C223 /* LifecycleBehaviorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D1F592A03F29834A482A527C26C43F1 /* LifecycleBehaviorViewController.swift */; }; + 42BC5786C34E1EB3171356AF8E67E607 /* Tab+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9457CFFC68284D195CF10F91CD0AB794 /* Tab+Adaptive.swift */; }; + 42D8642270868B9E53CD23BE32323A0C /* Tracking+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7852EA1E7C25798259AEA5BCE126639F /* Tracking+Adaptive.swift */; }; + 44B74653D503CB502B265C0366ABF103 /* it.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B7AD2BE9A6C9E2298E7917BF8FD6E425 /* it.lproj */; }; + 44FB46D5982B3E156F7AA4BEE081B463 /* FIRInstanceIDAPNSInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 88B5959D5B7A3E36DDEF6EA561F00502 /* FIRInstanceIDAPNSInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 45E7C2C769D51937061338A69BEE2316 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 46132B8EB028FC0BD59C6B8293151984 /* FIRMessagingPacketQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BA9EA5998AA76F74EE798C3CBBECA9D /* FIRMessagingPacketQueue.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 488F9DFC7A23F9EA87DA50076865695A /* GPBCodedInputStream_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = D7E5680FC53E7E9F3D5CDFD636890134 /* GPBCodedInputStream_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 48DD3117F88694C0FD530B7D951E585F /* UIImage+Tinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8E677CF6BD8B668E00639F75526D6FE /* UIImage+Tinting.swift */; }; + 49346BA8A9F65D4EB67A452D73543353 /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F4647B8C0D1352B1C58A2CCAC8F8A1 /* ServerTrustPolicy.swift */; }; + 49831F5B3224292A50B5E474627F4066 /* FIRAnalyticsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBA28A120B7A31F4D7E17E23F881916 /* FIRAnalyticsConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49894777E431600670C3413CFD08CBAC /* FIRInstanceIDKeyPairUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F4539DEEA1DD2E3E786DAB20A235E0B9 /* FIRInstanceIDKeyPairUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4996917AB6F783603F868111BEA8E18B /* OHHTTPStubsResponse+JSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 73047CD3A9D6F102084B6565479FD975 /* OHHTTPStubsResponse+JSON.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49A539B6B325126F22AC170396E5B6EC /* SDStatusBarOverriderPost8_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 180977BDD0E3E3ED4CC91DF5BCD29868 /* SDStatusBarOverriderPost8_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49B7354094136C862C02D3564F82F95C /* Emphasis.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45D8D0A1979A555EFB7FFB40FE9E3B3 /* Emphasis.swift */; }; + 49D4D750DDF02487C8AA4B26B1D85942 /* FIRInstanceIDKeyPair.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C37EAC158A77C4D6904556D7810ED89 /* FIRInstanceIDKeyPair.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 49FF7B5676B99AC5BC66CD274572D5F8 /* OHPathHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = F582E21899CB1B7DD3C29A9B5AB73287 /* OHPathHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BAB4E1DF3D4D6AF88A8508E3A2F09A8 /* FieldMask.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B333D83F4602F037A199CE1061A7A79 /* FieldMask.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C1E5B258AF3CD751A7D6DC2F9EFDB64 /* StringStyle+Part.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2CFBCCEE9CCE0907B805548198E2D4 /* StringStyle+Part.swift */; }; + 4C4E5BAB5F6CEF8DC0184E7045DE6319 /* FIRConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 106E91C219A27E966E2F6168D1D7F3CA /* FIRConfigurationInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C650C838B9A46B8869FAC4ED9167B3B /* SDStatusBarOverriderPost9_0.m in Sources */ = {isa = PBXBuildFile; fileRef = 047E636E2BACE2765A28ADD8F0A0E5CA /* SDStatusBarOverriderPost9_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4D4DD4E2E2F97F489820569260C7BBEF /* GULNetworkConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E381DBDE829EC743F4F0A730A0EA4E5 /* GULNetworkConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4DE36299CE267FCDD391EABEA81FFD85 /* SessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0CD839E48FC413F0F119BC2DF2B9FF2 /* SessionManager.swift */; }; + 4FC8500AC1BDC6610782C5C287EAFB46 /* SDStatusBarOverriderPost9_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 13EF5B0944ABC90005395BF63E59D1B9 /* SDStatusBarOverriderPost9_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5066B89BFDEBC3087F0077E0E19D605A /* FIRMessagingConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0951EED81BCFA0803E2B141DE332E11D /* FIRMessagingConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 50A0609DC011B95A498F342D6A496297 /* GPBDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 168D0C5421335ACFB5EBB53C584D8B5D /* GPBDescriptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 50B4399E699415F041C1E8E4DB7A1D07 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = F2181E7978D4D5EB57672242678285CA /* OHHTTPStubs+NSURLSessionConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 513E4B1817532226E5F18D5BC9616970 /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D5ABA89BFABB034F15503FA4EA2C665 /* Struct.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 515B9D3F0278919FFC0BA69A4A50BF3E /* AccessibilityHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 075A60A7C92F557056B739FD7E6BD32C /* AccessibilityHelpers.swift */; }; + 51E49408AF7F12CE0559236B11C26465 /* FIRApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 137550D164A3DC3110CE137D5BC383BE /* FIRApp.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 53DC83DDE0F07B1E642EDD0A2FDFCC1B /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E200831632A5DA6FE18A80ED063AA8 /* GPBMessage.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 55F7228A18EA4ADE7388939284DC1828 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4AA562F866C56D8D686538218F79EA /* FIRLibrary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 56284F2A2FBC7E52A29EA14CA7DC047A /* zh-Hans.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9217346EC5CA9E35B7D5CC7A1AC82A9B /* zh-Hans.lproj */; }; + 5709B0AB8B9B6E3FD552E4D0E72A40E5 /* FIRInstanceIDAuthService.m in Sources */ = {isa = PBXBuildFile; fileRef = 781146DAC6F2B33CBAB88F5B7480DA3C /* FIRInstanceIDAuthService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5762BA089A3300D0CC1348BB1C6BF5D0 /* FIRInstanceIDStringEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = EC198B2667B7ACBED262624C674F40C0 /* FIRInstanceIDStringEncoding.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 58052E699714C0A50B87E6259F53F415 /* PlaceholderTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59995D0C9E351E7C567DF118C940304B /* PlaceholderTextView.swift */; }; + 588888EDDEAB87B7AE65F4417BB0895E /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = E458A4DC6C3E79475F17EE8A2379E327 /* pb_common.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 59797280DBA2DF4FDD7E2FB08A37D99B /* GULUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 36624989E8CA8F0B22557AD8E3ACAEEF /* GULUserDefaults.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 59DB4ECFCA9DC741DFF14E4456709E22 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26820BF7BDA3D0A1D104CE81E2CF5EEE /* Notifications.swift */; }; + 5A08019AA5486E6DCA36E4EBD3C52A1F /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0EDF0E175A8ABAE1DC6C2A8C67270 /* Validation.swift */; }; + 5B7FBA1711906689F88D73F89241C604 /* Ligatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4EB1163B98FFAB7C42AB21C3ACF776 /* Ligatures.swift */; }; + 5D01F5103E9821505EF578009E14403E /* FirebaseInstanceID-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FD395C6B080D05AA0E9B521C84DE95C /* FirebaseInstanceID-dummy.m */; }; + 5D6901CB7E479AF1C5F8A340BABB727A /* GPBRuntimeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D50A2051D90DCC03E026A0A56A46F1E0 /* GPBRuntimeTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F12EFB41C6F7259375BF3E842CE980A /* SourceContext.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD0138F17C5CEC5217CDE58354221B3 /* SourceContext.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 61C1F86EDCE280896041FC1FC3DD8187 /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11A4E7961F768D0892E18D1649C5FE4 /* NetworkReachabilityManager.swift */; }; + 623966AD950C81665095F64F9D4201CB /* Pods-Services-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AF4C07CB531C2A20C075F1E2F27F9807 /* Pods-Services-dummy.m */; }; + 6239F27D209AFEA6F20DC38D2EA8BF53 /* NSURLRequest+HTTPBodyTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = 92B3A83AF7CBD24CFB27352A8A473464 /* NSURLRequest+HTTPBodyTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 625AC25C0B02E9914E2F7B57ECEDB850 /* Alamofire-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 01CDC0351ED7CEC107FB8A77489F99CE /* Alamofire-dummy.m */; }; + 629542A04865B500B62B43F92C8865D1 /* SimulatorStatusMagic-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EBEFE4F4DF5F7C86F8F3F2C30FC2380 /* SimulatorStatusMagic-dummy.m */; }; + 63E56D00C55C0A10C4B75F082AF81B6E /* GULMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = D8D631A479FBF2CC1551FFD90D0D6CCF /* GULMutableDictionary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 63EACF4772E7F89957A22DD4E216C3F6 /* FIRMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = E774767ADA7D8B661ACBB80E499003DD /* FIRMessaging.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 643932FF6C60A7B50E69281BEC283DCC /* GPBMessage_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 01FC0E2DFCCF55217572DC39EA5C6163 /* GPBMessage_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 64608DAE6E2BA2943D7382FC8434201E /* CubicBezier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE2591C629B8D1D99F7EB621AFE24BA /* CubicBezier.swift */; }; + 660EE0BDDC1B6E8665904E38D90D31C6 /* FIRInstanceID+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 18DE3A66023F031C118C9FA1671ACC93 /* FIRInstanceID+Private.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 66E368242E78C0FD771A32B6FE1931A8 /* FIRInstanceIDURLQueryItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 45BCED46E7DDF7FBA46DB0CC8B1E58EB /* FIRInstanceIDURLQueryItem.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 66EF408EFC3D695477CAAA86191FF5A2 /* SimulatorStatusMagic-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 422661E817D097522D8B376CDBD2FD9C /* SimulatorStatusMagic-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 66F6BC937ACA5E47AF09DB8ABB6D7645 /* FIRMessagingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C51C1D95A23094AED0ABE47DE23F077 /* FIRMessagingClient.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 672DC3874BA0AB02B90F8C35DE880034 /* Image+Tinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44A4945BC33C7C54BB4A7520594B486 /* Image+Tinting.swift */; }; + 67D67C17FCCB5F83FF620BD048630184 /* pb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 63782DD22D80D12F0478617EBF8A6E9E /* pb_common.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 67DE466AD41481FEF9115827C53B66FC /* StyleableUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E6EBF71B53225C8F92782A7CC19944 /* StyleableUIElement.swift */; }; + 68333497E7CEB0B383B8F14BF0B0B6BE /* GPBArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A12FC33DD08260C9C378A9C2A227833 /* GPBArray.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F48879AF4FFB5542723DDF132E7BBF /* FIRInstanceIDAuthKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = D5DE97AD0E8D2A97E134344E7227B548 /* FIRInstanceIDAuthKeyChain.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 69AB47B1E87B21D5AB731A8B4F8A5C6E /* FIRVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 772EBD4355380FAEEEE486F50277CA1F /* FIRVersion.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6A54BA358BA6EA4B21A472B16B0F2136 /* FIRMessagingPendingTopicsList.m in Sources */ = {isa = PBXBuildFile; fileRef = B67FA446F6A78388566D90BDD02B2175 /* FIRMessagingPendingTopicsList.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6A5EF7BFD9E1F744141F8FADA93CC40C /* FIRInstanceIDConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 11EF24F4E2A79E63296F2034D972DD0A /* FIRInstanceIDConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6A9ACBEB61712282B87B0A3090045B36 /* FirebaseInstanceID-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A86060F6B97532F283FE392A2B356F3F /* FirebaseInstanceID-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6AA8F0D7888C5B32C0D72865D646F69B /* FIRMessagingDataMessageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FB7E0D532911BBB43E2A8AF72818A0DD /* FIRMessagingDataMessageManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6AC487E61CBA42325EAEE431BBCCA6C0 /* FIRMessagingContextManagerService.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B4A56D8EB5978D426BDC59DC1AA5E2C /* FIRMessagingContextManagerService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6B02408E859D41775E7C99C72211E233 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 6B9902DEB83C255B7F7BE5B97D95CB8C /* FIRMessagingConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 67E6336A4DE03D2B54BB4E2D5C377405 /* FIRMessagingConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6C12C62F4EB60D4AD5F161942A4D7A1F /* UIViewController+Deselection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEB3012499F8855E88664D9000D9DCE4 /* UIViewController+Deselection.swift */; }; + 6C47FCB1BC1088F8D9ECA92E2D2C0EE1 /* OHHTTPStubsResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9D78BDFE3971F2EF43F1EE93290481 /* OHHTTPStubsResponse.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6C654A56978C6D1886240834580D72C3 /* Alamofire-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 55D73A9343E88A26AE65A4223D8C07DF /* Alamofire-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6D80417305501039BA0BDDB62948E193 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 6E8015F43C774A2A6B848A4850A5A01B /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F446B65463479D1A1BC7E615FB1DB21 /* AboutView.swift */; }; + 6F08BA4C77195B13666BF9D048734345 /* NSURLRequest+HTTPBodyTesting.m in Sources */ = {isa = PBXBuildFile; fileRef = FB31D468DB67CC3C68E932FF60724283 /* NSURLRequest+HTTPBodyTesting.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6F7B7BD79C3CFF57A0AA78D63E5E3875 /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D3820BB2870B22224C025F97B495A /* GPBDescriptor.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6F7BC8C09DBD46C7EAB60340AA5AD1A4 /* ru.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F6EDB24AD1F08BD38D4E0B70CC036804 /* ru.lproj */; }; + 6FA68690945C1A9D56524BE6EEB1B23F /* GULNSData+zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = 966E61D7CDD4B8F269B4C52F6C9D4E6F /* GULNSData+zlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 70A61B041ADCE42401597F1F1E36A137 /* FIRMessagingReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7750A59221DB77FAF80CF7B06B985ABA /* FIRMessagingReceiver.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 71775A89A3802A1BA58BF1BB41DDD9A1 /* FIRMessagingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = ED75C449FDA4BD587531DFEE93D42918 /* FIRMessagingUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 722C5094761B72D30EB0CCB1CBD1BB5A /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = D7EC6B48A447510995672266B84A0112 /* Empty.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 72E64E250ECE3FED90F8E229980CD42F /* FirebaseCore-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F3787E17CA4EF4DC7B09E88A20DD9847 /* FirebaseCore-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 730B332BFCCE80D74F954AB5D5018B07 /* FIRInstanceIDBackupExcludedPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 466630EDA0868AA0AB1CEBACE48F76AB /* FIRInstanceIDBackupExcludedPlist.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 73C84761F0777ED77BDA9657F0D88C33 /* FloatingPoint+Scale.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1364213BD031AD3BAD42D9E69571ADD /* FloatingPoint+Scale.swift */; }; + 748616D83CFB8AD5D5FC47C2EDB8FF36 /* GULAppDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DF740D3ACE024C9F6487F0DBFBBC4B7 /* GULAppDelegateSwizzler.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 74CFDB81D12600FF74EAF4FE27423E07 /* Protobuf-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A2450A9AC3AEDEE3814CEC1893EBE3F /* Protobuf-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 75123AA17FF6CF721675F5EFB25EC559 /* FIRInstanceIDCheckinService.m in Sources */ = {isa = PBXBuildFile; fileRef = 44001909662AEC3C8F8AB4E8044AB034 /* FIRInstanceIDCheckinService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 756BA8556D315CD499501E923700528F /* GULNetworkLoggerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = E7BDF86CE64C4E407EBF8A73A20C6EF3 /* GULNetworkLoggerProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 75B139101E0BFF3585B49F931BE977F2 /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = 186880608DAD6477417FCC20081E68DF /* FIRInstanceIDCheckinPreferences+Internal.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 760970F7357E9ECCDFF141830982057F /* GPBWireFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 053874D026363AC0A03A09A01558AD61 /* GPBWireFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77399B95DEEE5E953DF7BADB4B7139D7 /* FIRApp.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D1E9800DF9216163D243A25E5A7E22 /* FIRApp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 776CAB01CC996B0FBA52C7C6872F0814 /* FIRMessagingClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 318F5854818D012A621F4EE3E8A310B3 /* FIRMessagingClient.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 786F3F286C9376BDF33F3008E351E6F5 /* OHPathHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 894FB1F3B5CAA20D3A8E5DA58FA415A3 /* OHPathHelpers.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7898A06A3FFC4228F5FC1CD65A7B8F94 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D6B1D921CE2EF324C684690E9B44CD4 /* AFError.swift */; }; + 790C5DA2D20D2290D35CD413F051C02D /* Shapes.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD38CBF4748B96190468E88F12A2064 /* Shapes.swift */; }; + 79D254191EAC73996F5BD06EFFA4E649 /* FIRInstanceIDTokenInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C1593407CAC28F4349FBA65B0C1BD9 /* FIRInstanceIDTokenInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7A746727440E0883EC1F855F0CBA10DC /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 773F43FA50FABF1CE0C562282F32D624 /* DispatchQueue+Alamofire.swift */; }; + 7A9842F18B9A92D8C8A029ED721E22B3 /* nanopb-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AD9FCFD914EDA9CDBDE1BA40686E48E0 /* nanopb-dummy.m */; }; + 7AB1BE129580DE43994C27204D3D9F97 /* FIRInstanceIDConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = A48A79CAAFF110C87DF8BF807837AB83 /* FIRInstanceIDConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7B9E46226BDFABC5A56EACCCAB550F13 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CFCAB771CD0ED282F14A09984871047 /* MultipartFormData.swift */; }; + 7BDE5F52B1111A7404B4B32EF8C5857E /* OHHTTPStubs-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B7A403AA64C0558925444F207EEADE76 /* OHHTTPStubs-dummy.m */; }; + 7C9F9297EAC2E0A5302B50564B575B0A /* Empty.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = B3B80947892AFE99F690D90E0E6F7A0C /* Empty.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7D4B4A11129ABEBE81CF0A75213D2927 /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D79D6EFCA519A3D859AD623DEEA3E97 /* Alamofire.swift */; }; + 7D8BB2A430E5C20AF8657A11C9F48016 /* LicenseFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B77C6FBEB46883FCDBBBF0333AAA959 /* LicenseFormatter.swift */; }; + 7D9390DFB58EAEF71DA1CE4E5F4AA98D /* FIRInstanceIDTokenFetchOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FD4F06E7B97586342DC5F130C93CAD6 /* FIRInstanceIDTokenFetchOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7E9687A54B05381DCB9BAAEA72366EA7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 7EAB3629AFCDDB950B9A4C610588D97A /* FIRMessagingExtensionHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC07246B7DD7857DA18E71CDAD1E01D4 /* FIRMessagingExtensionHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7EEA98DF6EA7BC488FC2C7DC4579BD86 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2207F5B391C14F1738C82A01AFB21DD1 /* Security.framework */; }; + 7F665E687CD8C311206F990CD0DA7418 /* Struct.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A62C867EDE3F5810D57F99ED04E9BA0 /* Struct.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8060AA86BCD21633E21A8DA29FD56D07 /* GPBUnknownFieldSet_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BE9D1869AAADCD42062E01D5D3C87C8 /* GPBUnknownFieldSet_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 807B6E3FF4C4A97577F4D5EDDDD49ECC /* Duration.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 5805433E9EE4075EBAE342A288525AD4 /* Duration.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 80975D2BEC9BBEB5D026A75D9A42B6B2 /* GoogleUtilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 44CE758ABDDC428058091BE3EF7C9451 /* GoogleUtilities-dummy.m */; }; + 816CD4237A652BDEADE317F1DD341A0E /* GULSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 47EBEF062D1954D670444D5FB49CB050 /* GULSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 817FFB25CEB300C681DBD8283FF19BA1 /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = C0865174F215EE5541472B794F16EABD /* SourceContext.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 82FEC2B074B1B137D892D51E72F583D5 /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = BBF0EE4B9DF20FB5E0DF535FED448A7E /* pb_decode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 837BDD2C7B095A5B3544B3B632ADA738 /* FIRInstanceIDTokenOperation+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 571718858875E6D21B448DAAA8A43D00 /* FIRInstanceIDTokenOperation+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 83CA30B037DEB0527448F9C54F396B2E /* FIRInstanceIDAuthKeyChain.h in Headers */ = {isa = PBXBuildFile; fileRef = CE04EB1BD0E0D76A2673A8C0C3366119 /* FIRInstanceIDAuthKeyChain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8494ADF872F49EA36C4844F0298DD498 /* OHHTTPStubs-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F6F1BBF9B142B5EF49F87D2D044E829 /* OHHTTPStubs-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84F2EA2BB1C1901EA0A3A1F71919F915 /* CGSize+DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FDAAF328CFC1916BD31D012F33FA11 /* CGSize+DeviceSize.swift */; }; + 857CEBBEB16312172E8DF03B1147377B /* GtalkCore.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 21518DB69A5249884D47AA1C030D65A1 /* GtalkCore.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8625F2607D15296CF239BC97F7BB3EE6 /* FIRMessagingCheckinService.m in Sources */ = {isa = PBXBuildFile; fileRef = 44A66697CB999F1B94BE112FF3F6082E /* FIRMessagingCheckinService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 884A014FF635DEF5D4FBF2CED48D3610 /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F6EBA7C6997FF0B01735341A694592F /* Type.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 88E84F132638AF1A4D47AC5A0641131F /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = B7873C854D420CA53D1BD7CE0700ACDC /* FieldMask.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 890D4B46D1BE3870CA15607A41327FAF /* GPBMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B179EF2E474E501FD5650C4ADF83782 /* GPBMessage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8A3030124B1B48425552E80DADE1FA88 /* FIRDependency.m in Sources */ = {isa = PBXBuildFile; fileRef = FF710E85F020077130E558211B5B8D8A /* FIRDependency.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8A8D4BB3B21FE7CECDAA6908E6886531 /* FIRMessagingPubSubRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 849FE1C62D5BADA93D12508A10FFB88A /* FIRMessagingPubSubRegistrar.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8B512506674B51BA6D35237363F2B370 /* SDStatusBarOverriderPost10_0.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F243E68DA74E3EF1064781840A6375 /* SDStatusBarOverriderPost10_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8C435621C8561A336FCB112215CE7F06 /* GPBUtilities_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8466929A49CE3221978EB36183FD35BA /* GPBUtilities_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8CCB4DFC6700B70BDB65D48791A47479 /* zh-Hant.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B732E75D7C970C6F08CDE5C6AFDF8702 /* zh-Hant.lproj */; }; + 8CDCC6382693D52163B893E94EDE484A /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = BDF0BD64F7D053FC261E77000D9D5B27 /* pb_encode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8D1F1562F8784E50D8E14D44A8B915ED /* DefaultBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA144693E6BF8FE7CAC6E965241CE03D /* DefaultBehaviors.swift */; }; + 8D56B87617552C4649123F283D3F4383 /* FirebaseCore-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A78104E9B1CB747B9ACC895D21681C1E /* FirebaseCore-dummy.m */; }; + 8D67D48F9FE60EA4ECB227C7E5E988BA /* UIKit+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547CDF4449B3AF5D1990F54FD639448E /* UIKit+Helpers.swift */; }; + 8D769B1E75C52E3BFAC64ABA8CA438FE /* FIRMessagingLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = E2B37DD9690B667E67C7B749014FDAE6 /* FIRMessagingLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8D8C7DD544D90026F85550B2CC95CBD5 /* GULNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 71D265F83D526F8D4CBAF591F57A1C35 /* GULNetwork.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8DB74A47E65D6DF7F9632EA8709028C7 /* FIRInstanceIDTokenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B80D74D41E215EDC00F1A0D8245EC63E /* FIRInstanceIDTokenManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8E06E338A8F1324484A07E102C6085CB /* FIRMessagingExtensionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CFEFDB61382511167CBE5BFA016DFF7 /* FIRMessagingExtensionHelper.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8E1278F983579FE2CCEED68C625ABFF6 /* SDStatusBarOverriderPost12_0.m in Sources */ = {isa = PBXBuildFile; fileRef = CC67002EE29757073391E2064F1BD0E6 /* SDStatusBarOverriderPost12_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8E1D665623C95E8500B9B69BFE963089 /* IndexPath+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6605561032963C6225A616C84441A72F /* IndexPath+Extensions.swift */; }; + 8E307CE212F087956B2835C792FFC79C /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E629EB70356C8FA1AD9781584EA8374 /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m */; }; + 8EC15CDA263AE10AF1D49B82794AFBB4 /* GULNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = DC604E06843C199B7238C7ECCDD65231 /* GULNetwork.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8EFC6634D956643DB4EB307460CE67D0 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A10B633A7F6F7DB8565FCD54B2F6015 /* GPBDictionary.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8F1FF94F0311B30034EF2698971AD690 /* es.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9917CC431DC36BB3D118B1AA7A204319 /* es.lproj */; }; + 8F7F70BA374635820D060762A15931D3 /* SDStatusBarManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CD626DB394FDD0FF51FD012D20A334F0 /* SDStatusBarManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8FBBD77BDF34DDAA858E757318F1FAC5 /* GULReachabilityChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E3AE25C553C268ECABA7BA60383152 /* GULReachabilityChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8FD25BB2E0968A8C1C27B4383552FB40 /* Clamping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526F1F36C6164054C3753D3E4D5C5C6B /* Clamping.swift */; }; + 90CDCAD92FF576BA1E27CAC55DF10C91 /* FIRInstanceIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F00E32E42A1E8D5237611B57EB97BFC /* FIRInstanceIDStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 917E9C7AF939B0FFD3C026BB4EAC73DF /* FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 677C759A60BA1A68EC54588ED16024FD /* FIRInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 91E15F3267E641CB6282B424CE389263 /* ko.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1683A78B7B9007625AE95AAE42A96663 /* ko.lproj */; }; + 922299C14975D3257CEA7CD05B8230AA /* FIRMessagingRemoteNotificationsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = E689A6FA791FBDA83E75CA835495CE84 /* FIRMessagingRemoteNotificationsProxy.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9243AFCD79CC422AC3AE16E6CB0C262D /* FIRInstanceIDAPNSInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 046CA33B599DC985AC83516113232E99 /* FIRInstanceIDAPNSInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 92716A0085066BCCB43369069E76403A /* GULNetworkURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 8239448521ADE6944ED02A4E4E8F83C5 /* GULNetworkURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9307183A631102399452F35E8630D4C1 /* Priority.swift in Sources */ = {isa = PBXBuildFile; fileRef = 968AD6C6067177F3FFBF4E22B5D62AFA /* Priority.swift */; }; + 9335522C7018277CE54C18E182A5A1F4 /* SDStatusBarOverriderPost9_3.h in Headers */ = {isa = PBXBuildFile; fileRef = C40BAC08597BADB1064666DF2633CF2D /* SDStatusBarOverriderPost9_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93B158CFAE0146108F8D3DF1F5DF2FEE /* FIRMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8948FFD9D354F2001C98CEE8B45E08 /* FIRMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93F97DB70699CDB8C433DEB03991621E /* GPBUnknownField.h in Headers */ = {isa = PBXBuildFile; fileRef = 58BC5AB95FAF621615835A4436B69D8C /* GPBUnknownField.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93FE3279105620965FABBD2F6D30ADB1 /* FIRInstanceIDVersionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0940BB70F444E65F6DB52323B97369 /* FIRInstanceIDVersionUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 93FEDE6C16994FA82F27CC56168013FF /* GPBArray_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = D9011FC16F020AA7453970FDC70281F4 /* GPBArray_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 949E82C19D7A44BEA21AE96476C2E533 /* FIRInstanceIDBackupExcludedPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = B8D3618FE4C32D4ADBE22D247745AB5F /* FIRInstanceIDBackupExcludedPlist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 94E0EEAC1123DEFF7625B88F0E71E3E9 /* FIRAnalyticsConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2C2A90AABD3780C5969C4B208AF34F /* FIRAnalyticsConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 94F0EFD969D064F5D663A6EE835D4516 /* FIRMessagingDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = B8E0195AADB4B77EBBA26DCB16A7ADB1 /* FIRMessagingDefines.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 95C6E0D347DA6F768468BF0929F8A84C /* UIView+KeyboardLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 365D0C4EEEA6C8DB030220CF3E73772A /* UIView+KeyboardLayoutGuide.swift */; }; + 96468709B156DCAC50DABCA9CB197F21 /* FIRMessagingRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 5725B7F7891756CBC38A7C3FFBA0605D /* FIRMessagingRegistrar.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 969588515E0889063CB93DA45160D18A /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = E82C57A8834CD3A374E5E52A9DEBA80E /* GPBUnknownField.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 97C1EB978E9BF15E1F44EA79EAB899E3 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D3E35ACC5108C1B4DEF24DD53900541 /* Keychain.swift */; }; + 9811AF1663228E41A0F9116F3FDAB4D3 /* FirebaseMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A68AA6C83230BBFED7CC97DA09A987B /* FirebaseMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 988E2668D29D51B8304BC24235BA15B6 /* FirebaseMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6FB40F4F28DA6BC422DDDDBBC7CDA6 /* FirebaseMessaging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 989554E915C48AB0868348384AE545C8 /* FIRMessagingDelayedMessageQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = B1EEA6318B7652582ADC0248EF0E862A /* FIRMessagingDelayedMessageQueue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9895E36F7164AEA6EFADE585598C4B9F /* FIRIMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = D46CD8B2E3B48A9900B0D54DC022F51E /* FIRIMessageCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 98F45B8FD93C9BF709915C0ACC7D316D /* DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC35B00BCB6D00D5DC095E60BA6F8D5 /* DeviceSize.swift */; }; + 9A7E0722E552D06D26AF4A48C0FC02C7 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 536F55571CB5D4E8C4CD313EFFC98897 /* GPBCodedInputStream.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9AEA26145F40861CBB60CF404C36C469 /* UIColor+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = E036B66F0200BB21E6A3C50B4A98D7C8 /* UIColor+Helpers.swift */; }; + 9B713E8E0EFE0EA70A995827E5394683 /* GULLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D1AB7F35E8D9D69E2A3E30D0AFA1F1 /* GULLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9C24AF3D249563A26F59EDFBA4C7773A /* FIRMessagingRmqManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BCBB2D56D50E44BD77F0169A7F75E7B /* FIRMessagingRmqManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9C27962A6C09FD001BE83B3873C40856 /* FIRMessagingAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 98DE82806BC35C7A7C3ACBCF0C7B379F /* FIRMessagingAnalytics.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9D37E82FFBA10D1CAC0BE6FA8C3B17E2 /* Compatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE96786D662F36B014DB2976712E52D /* Compatibility.swift */; }; + 9D86C6E7427763F4CC75403A37ECB547 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 9DD886828EFFBBDB2439ED4B11CE081B /* SDStatusBarOverriderPost12_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 322AE82498430F3AA39C51C2BC4FB15F /* SDStatusBarOverriderPost12_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9E2AC1BC432B98F9B748D05D7B488CB0 /* OHHTTPStubsResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A3F12E1757587C015AB1F285348CFAB /* OHHTTPStubsResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9FBAB5AB3AFE3F48C77BAD0033828124 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + A00E351731E9CCAE152C5B88D885F776 /* en.lproj in Resources */ = {isa = PBXBuildFile; fileRef = DFDA0DE503139F615A5FB983A7BAFD1A /* en.lproj */; }; + A0A162DA5D4BB9A0DAFA3B60DE55130B /* UIViewController+Lifecycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA99AA3900C0A75CF6AFE7E2BEF2A0 /* UIViewController+Lifecycle.swift */; }; + A0DD808CD41CE6A758A3C64289598B2F /* Anchorage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 031FC7BA2605BE0368D9692DBDC15D81 /* Anchorage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A0F9B76BF94A692BF96E87085472F70D /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 37D1089A0FB89C55B768CC26C804A7B2 /* GPBExtensionRegistry.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A142ABBB6E27723CB76393007499BBCC /* SDStatusBarOverriderPost10_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 76848D31B6A54F9167B3E81B2B157273 /* SDStatusBarOverriderPost10_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A18D4637F3EB0E9D08ABB14CE34737CF /* FIRMessagingSyncMessageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B7A5E48BA4D6DE7CABBE36B040019834 /* FIRMessagingSyncMessageManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A263672C857DB63F9F371F1E52FDE51A /* BetterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6B719E9A14C1E430887BE3B805CDDE2 /* BetterButton.swift */; }; + A2C760AD1904241031DE9DDD5DB0E935 /* GtalkExtensions.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = B4C8749E960A855A7C7965EC2BA8218A /* GtalkExtensions.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A3492135E0BFF1F6BE2DB3BCB52907C7 /* KeychainAccess-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EF45F089BAE93FE828CD9688AA8CA8A /* KeychainAccess-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A3A7C1C339F3BDCF7DAE115107D4FC89 /* FIRInstanceIDCheckinPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = E2E3405DF921FD6575E7698CA8B86D62 /* FIRInstanceIDCheckinPreferences.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A4D4A302AEEB0666AEB08B226637D78E /* FIRInstanceIDTokenFetchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = FD58305059DB6EF784EF634B198DD3CB /* FIRInstanceIDTokenFetchOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A5F185E6FD5C3BBCF46BF62774965E31 /* FIRInstanceIDLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = BAEE38A7456029D2435589A2AB61BB54 /* FIRInstanceIDLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A605E2BA73843B1BF04318D1F249E7D8 /* FIRInstanceIDKeyPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C526BDE19AC726B077CA91F4A3D248 /* FIRInstanceIDKeyPair.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A6413A77105FCE014808660C4A174018 /* FIRMessagingAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AAD5AF881A90E6C8ABB964271CD3D7F /* FIRMessagingAnalytics.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A6DB0753F4D2BE9056C288F6376CD092 /* FIRComponentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 990D5BCA382BD9D9D2C3C1E291F2B135 /* FIRComponentType.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A7140404957904FEA7F3949F01B858C0 /* AnchorGroupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F6E205211513A677E520BAD5BD8C183 /* AnchorGroupProvider.swift */; }; + A7A6BF0C62BC3FC2F757468C317099EE /* FirebaseInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D5C9E49FD0B96CC5F0A774F637668F2 /* FirebaseInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A818814179D868596CE5F1BC13302BB3 /* GULNetworkMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 35D0212C3DBD3EB9B48F92FE6E705124 /* GULNetworkMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A85388EF392B19C59DC3C5F54AE550BB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + AA174969F3D235A0D986C40FA01F8696 /* SDStatusBarOverriderPost10_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 21921F807B4B34CE95F4333954EF9330 /* SDStatusBarOverriderPost10_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AA2AA7707B86A60F4E9CCA3E1BE504CA /* GULReachabilityMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B6B0B82C4B090FD5CCE3E4B3185607 /* GULReachabilityMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + AAA60349DF99530BA4F476C8D9DF2AC7 /* FIRInstanceIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF524EA9012A4ACFCAD0BF6C7247299 /* FIRInstanceIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AB7B824DA74A18F8F235023186B0CB99 /* FIRInstanceIDKeyPairUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C5090975983CFFFD9CB40E0075C0D038 /* FIRInstanceIDKeyPairUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AC38CF40E73B97EFAB79BBE6B56C8731 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = D362F402CE5684297570016D7825F239 /* Request.swift */; }; + ACF4FD5B728533D8559BB12F6428EC2E /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367EF090BA9D626CCBE6C72374BAB47B /* ParameterEncoding.swift */; }; + ADEAD2F9475DADEA607C02D303956EBC /* FIRMessagingPubSubRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = ABF027D832F3CFAAE988298C13DB25CF /* FIRMessagingPubSubRegistrar.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AE1DA43BC4C87D79899149013C1DAD98 /* FIRMessagingDataMessageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E735845AC66A0F18361E9CB0A620082A /* FIRMessagingDataMessageManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AE2FB5B79FD2943549EF53126CD94862 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C4060169D4E6873CF1EEF2A457AC3BD6 /* GPBUtilities.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AED93C5125D8ADFC97325BC4BDEE8F53 /* cs.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 74BE747D93A2FF0D9596DFEB89B88506 /* cs.lproj */; }; + AF9BB102EA05092BA8BAB13BCA806CEB /* tr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = AB8C0F48EBA2E62C0D0D696427AAF734 /* tr.lproj */; }; + AFA19EAA3DF13F4E416F836CDE2C1251 /* FontInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E07B09F7C15576A3A444C774F45026FA /* FontInspector.swift */; }; + B070DBBE6F946A656405E140E975A211 /* GULAppEnvironmentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 5439C399E40C811A0CC58CD80BF419DB /* GULAppEnvironmentUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B075936A698C95B193BF870AF0C5DE9C /* GULAppDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 60057B688B56F5C62D15997BB9EDEFDD /* GULAppDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B1169761CF66CB7C48BFF5F13A2A89A6 /* SDStatusBarOverriderPre8_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 433FD3F0C39CB9CDDF7F51F624242518 /* SDStatusBarOverriderPre8_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B1AB9C0D1668DA7D1FB8B05625FE15BB /* NavBarHairlineFadeBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 441C8E5411061099355CF78039DCB16A /* NavBarHairlineFadeBehavior.swift */; }; + B21176F4F4CEC62BCAFC4FEB1712C2B6 /* AcknowledgementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF86C6514C399C0918A89B10C69289BA /* AcknowledgementViewController.swift */; }; + B26BD92ADC60A9F477AF155252F41C61 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + B2C05E981C8FAAEA0F53F712918CBEBF /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D75377169BF1143EF206F74484FC1F0 /* Timestamp.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B39604A46A4903C262D18E317F1E6C6C /* FIRInstanceIDKeyPairStore.h in Headers */ = {isa = PBXBuildFile; fileRef = EA44C89EDF2C4365821C353514E832DF /* FIRInstanceIDKeyPairStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B45A8A82A0FD4C548C6DB743E8095E86 /* SDStatusBarOverriderPost8_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F88E4F0E3A11E9B5D721DEEDEB2F09 /* SDStatusBarOverriderPost8_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B4B77955EC2C522E041EBA397F87FE65 /* GULReachabilityChecker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = EFBAAB841881AAAD3B071BA31361B288 /* GULReachabilityChecker+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B501012C85EBF16411A4B9CF856A3044 /* BonMot-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F7535A4C380C47E118395A613AF3D849 /* BonMot-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B563C657D3678F851A0F8881DC90DB25 /* Compatability.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF22CC9C8607DFE61523790B4E8080FC /* Compatability.swift */; }; + B5E3F3D139F7AC7686281E983CAEC0B9 /* FIRInstanceIDUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB3FA695D6D0C669DA36186435E474 /* FIRInstanceIDUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B60414F93325024469AAB0F4B1D4141E /* FeedbackPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6228C304CE54B8A03AEF3954707FB619 /* FeedbackPresenter.swift */; }; + B6D9136FE482A5716B99CAE6FF7545F4 /* GPBDictionary_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D7113D1B1F68315334A5D6E5C78151A /* GPBDictionary_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B734B64212F2A039FCAC85F14608AACA /* GPBExtensionInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 780F31022D4CCCEEEF6B0433A8907F93 /* GPBExtensionInternals.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C5257CFBE55442EECF051DF82E729B /* FIRMessagingReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D090276832D4024D8B3A5568BEA4DE /* FIRMessagingReceiver.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B9AFBB66C67E71F0BFDD0DE5687C9CBC /* GPBCodedOutputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E6D0C984DDF42A7E6B78C3EAE3C981CB /* GPBCodedOutputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BA0C33AE7563904D128CB643510CCBE3 /* FIRMessagingPersistentSyncMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = E19C54CB57055FAC1B7EC1A332B36AE1 /* FIRMessagingPersistentSyncMessage.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BAA7A298BF2D071AE6077551CABDA17A /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A99BF2E906BA57B9D716EC2F28447CF /* Log.swift */; }; + BAB7813CCBF7A137B84D0EAFC620B6DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A467A3E9E3137B15241AA445AAA69D3 /* CoreData.framework */; }; + BBE95066A8DC1C8D8CC907000D70541A /* NSDictionary+FIRMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = BE03FBD1AE757BEDE8D7B21466965FD1 /* NSDictionary+FIRMessaging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BC256D583C7221D6FE3DC13F08C02FEA /* GULLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D45D29B213853B66B8B282991CCF083 /* GULLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BD9628048902C3E6580C8916350A4EE7 /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E5D20BCCFC283EBF43CD654944F92FB /* Any.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BE2C9A27C741D9C0773B4037E0D68B57 /* GPBDescriptor_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 399A0F9FCF8F163E53341ADFC13A530F /* GPBDescriptor_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BEC7476DE1CF263A31FA893D2B2A2E70 /* FIRInstanceID+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 10D13A0F900275F0E08660D22CBD3BD7 /* FIRInstanceID+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BEF4756AFAB837E4497F73F05DEDEECC /* FIRLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = B02CBEEE2EAAE48F5C59A0748E149382 /* FIRLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BF4C76B8E0C15E7C2A4762EBB84872F0 /* Wrappers.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE6952B80D386C75EA01A7B003A923F /* Wrappers.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BFD1F6C176B28F48CCF2BA6577A6C170 /* FIRInstanceIDTokenDeleteOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 78277DF682670FCB6D1E611B6DD72010 /* FIRInstanceIDTokenDeleteOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C1676FB1FF537AED93DB44C1582AC152 /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = A23C1F66FE104A9AB25DB49ABA41F52E /* ResponseSerialization.swift */; }; + C19BF82AAEAC7AD417C728F4C00B58CE /* FIRMessagingVersionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 4707DEF6F61CF955E8D0164566D43983 /* FIRMessagingVersionUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C2158E550AEB96660AD13D089D75543B /* OHHTTPStubsMethodSwizzling.h in Headers */ = {isa = PBXBuildFile; fileRef = DA1CB779343A19D8C026EA3A9FD492D0 /* OHHTTPStubsMethodSwizzling.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C264488148DA19FD69AD0378C76E7DB9 /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = E274690FABF5774F0512B21622B9BAD0 /* GPBExtensionInternals.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C289B85A33500EE2453F08CE5D0DB7EC /* GoogleUtilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A64AD290563189B5EC09536986EEA27C /* GoogleUtilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2DFB45D6494E63C9993006A15DE55B8 /* CurveProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88DB8688B47BE7D71F76B016AD52DA8 /* CurveProvider.swift */; }; + C329C3A3A838C4AD86611F67A10BFEAF /* NSError+FIRMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F619742AF64CEB785C8717E281D3DA7 /* NSError+FIRMessaging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C7EC6507F6038550A48154729F095B52 /* de.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C8268059830026F500EAD6383BB19F88 /* de.lproj */; }; + C8A5AA38971136EED1E4BC61205A591B /* FirebaseCore.h in Headers */ = {isa = PBXBuildFile; fileRef = CEC8FF8EB54F243F318CF7B7F16F7278 /* FirebaseCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C8AC529DAADB07541D2D33E392CDF169 /* FIRMessagingDelayedMessageQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 468332F23F5D358DB2288F3934AEC350 /* FIRMessagingDelayedMessageQueue.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C8BF91ECAD3BF591B752B6C3BCB6761D /* Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA2C241BE9B8942C2622A8288159183 /* Internal.swift */; }; + C9157A5A1365EB4A1D49EC2E8619E4F7 /* FIRMessagingTopicOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 88C8386A2D3A8315518D7FC2CF01A15B /* FIRMessagingTopicOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C92E53E0F9CE7D32CAEE125353487361 /* FieldValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2FA012779DEECE2BC6CC90C6E90407 /* FieldValidator.swift */; }; + CA260A0E0878CEE776DE12492DF46949 /* pb_decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 322D077B4897B4E6A8C083170A121575 /* pb_decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA4CD125AEC29FD189D003762B57494A /* OHHTTPStubsResponse+JSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 247C04FA03FB22629ED9C337A195F8F6 /* OHHTTPStubsResponse+JSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA601EE9EDA47E65195D3BF43930A270 /* SDStatusBarOverriderPre8_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F937168226D3E9CD0FDFCA1B32629DA /* SDStatusBarOverriderPre8_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA9D644E80935F7226B7D7105E837792 /* FIRMessagingSyncMessageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B4625D667AFBD9425C3A79449E05F451 /* FIRMessagingSyncMessageManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CAE0EBE0C0215C8BD9ACB0BD0562526F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + CB0F1A83E1DFE29F971867BFB285B59D /* GULMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B5E83DF94AA1871CCE123E6D44F0B70 /* GULMutableDictionary.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CBBFF56D23D20E974E5D8DF04EF3637B /* GULUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 807724545CC9FBB3B33672198DD057ED /* GULUserDefaults.h */; settings = {ATTRIBUTES = (Private, ); }; }; + CD780A5F99BC76FD2C51EEF2E495CACA /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD145FCE40536EC56F550EF22AE3A2B3 /* GradientView.swift */; }; + CDA29493785FE82167BBBD3348DFB2D5 /* ContextualAlternates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2707310D83A1EE6275AED80C0CF694FE /* ContextualAlternates.swift */; }; + CDE4C38B065973A40B8B7C844D236F86 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */; }; + CE60B4B85D17A08CA721EEE416CD1C83 /* GPBCodedInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D827CD1FACB9020945F3B62976196F5 /* GPBCodedInputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CE8F8AFEE45337F90EBA0EB35A82939E /* FIRInstanceIDCheckinPreferences_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E28DADD6AFEF6A2BABCAA95C90585AE /* FIRInstanceIDCheckinPreferences_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D0015B5606D3E07958B6F40D8625B8F0 /* FIRInstanceIDKeyPairStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 13811593551EEF5606EAEAC864156243 /* FIRInstanceIDKeyPairStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D05BF98677EB4739C37C9533E8D877A0 /* NamedStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 288D811BFAFF4D05B72871868528971C /* NamedStyles.swift */; }; + D05E35FCFD0AD588208B9A3258ED8F9C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + D08829137C1C28D74067CE0D2C9EEF00 /* UITextView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2765A7D6EF27B9AB42D6279A14D1669A /* UITextView+Extensions.swift */; }; + D2801FDD33B72D4C72A170C413AA7D71 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 814B71C2E085A900096EC6AECF6B4CE3 /* GPBWireFormat.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D3044F1325FD2E1F21B84CB5E9F5CD86 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = B2127ADF7134D22A7B41243F58B119B2 /* GPBUnknownFieldSet.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D33AB83EB8EE0B969A5F68BAF790EC60 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 829A957DF3BA4C53A538E446773D71B8 /* AppInfo.swift */; }; + D3B02CDBEEA6CB4AFA124B0D8FA73C06 /* OHHTTPStubsSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D5703DE6D32E8BEE77AC1C2A64D12F /* OHHTTPStubsSwift.swift */; }; + D448F684FAE5EF02A10E467A097B2B8E /* Any.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 22D1FCC1043B4DD3CEA939877906ECD8 /* Any.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D46809D86D5BB4EBB9AA10F29979A860 /* FIRMessagingConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 360D12ED7F2D4981DBE39DE4FCDC76A3 /* FIRMessagingConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D47C36356662BB1CCEC086A9339876E0 /* TintedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F5BB4D560F726BDE1F35DA184B1268B /* TintedButton.swift */; }; + D4EB284204E633D9175B0D5D850EB0EE /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = CE3DE9896DF364A9A8E70FBF3411CAAD /* FIRComponent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D560EF907E1B219904938C32DCA07877 /* TableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245165C00B0AB8EFA8DF3D2BBC1F3C8D /* TableSection.swift */; }; + D6F46C2555BF94DD17EB5C5137297B7A /* FIRConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B7024F62947EF6E2C6FB6CD5B34E2ED /* FIRConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D7B354F43D71BF171E85F1A3D460C027 /* FIRInstanceIDCheckinPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = F7515C947EF6212592653822C53CC690 /* FIRInstanceIDCheckinPreferences.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D7F5B4B7FF371A59B9F5625EC8ECAA7E /* FIRMessagingConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = AD183A51FD1FF965003291AC5F048C14 /* FIRMessagingConnection.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D8342F77FCB434AAD8975E0386F61252 /* XMLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1C7DAA26B8EA104B1A50DE2EC3AF35 /* XMLBuilder.swift */; }; + D86369D98CDF2CD116CBC4B66B089CEB /* Api.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = C392AFDD980E1C6B8554B9CCE3D4F95A /* Api.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D8C1006C39A3ED7B8F0EBF65D2E66303 /* Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23F5E88F86F777E70C48C646149BA42B /* Transform.swift */; }; + D9D8875B70BCDA90E099D5BA8A43A802 /* Compatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FCB1518EBBFFD314F997C63F2AE720F /* Compatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA1DCD65BFC20A27214C1138C1B92D7F /* StylisticAlternates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33CE071F3F3081B71DA145EC68A99E8 /* StylisticAlternates.swift */; }; + DA40FB231BD634D57A958BF90B7D27B0 /* FIRInstanceIDVersionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = E90EB60C7D8B2CBCC777305E2D53F83F /* FIRInstanceIDVersionUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DA5908E1CF98667FAE1CBEC76D355CA4 /* FIRAppAssociationRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = F0821896A90AE916F84B3E580249644D /* FIRAppAssociationRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DA8774937F99D03BE90B136C8A6A3C55 /* SDStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 65DFDCD7CA8EB72916D84A809A50C7FD /* SDStatusBarManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DBC85A7FC433639F2460B8ACA3A55882 /* pl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 842142B2B14A0BA4AFCC17CBAC0F7C98 /* pl.lproj */; }; + DC5DA57E4485C2FC85FDF53428C747DF /* FIRInstanceIDURLQueryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E1E27256DFC0F8898600F8DA01A1D3E /* FIRInstanceIDURLQueryItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DC6F351B5AAB3C9A2D73772E8BD102B6 /* NSAttributedString+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A4ECCE028DEB376DB17F98A1E4451E /* NSAttributedString+Adaptive.swift */; }; + DC7608F13970D10F8031C34305B4E2FB /* EmbeddedTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B74880F26CD1B4204F6539C5B5502D2E /* EmbeddedTransformation.swift */; }; + DCE2544D0E3CA203C5FC20C01510DDC3 /* NSDictionary+FIRMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = BA59223CF8122E668F27A492727DA05A /* NSDictionary+FIRMessaging.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DCED874D6F57DD0E744C345B53E96C3B /* OHHTTPStubs.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE96B90011674F188BAA0598BD91B53 /* OHHTTPStubs.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DD1C25E78F7402AFE7D53F6CB0EC6459 /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4A5B8EBEA544128E7C93E89A933ACE /* GPBRootObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DD34CF52B04302F2F486A626A57EBE9B /* FIRMessagingPersistentSyncMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 356BEB97A3924CA7A9EFA6E39B529298 /* FIRMessagingPersistentSyncMessage.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DD904DE0D282B9A9724B76536A085559 /* FIRMessagingTopicOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D0CAF61CDA366988A208A7B3648AB10 /* FIRMessagingTopicOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DEB02DD77A9565F861100EC194EA6E99 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6010A7276EC10495D966DCFE5E3C113E /* CFNetwork.framework */; }; + DFADB7B9266D1032D5BF21F2F1D02D96 /* pb_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = E862D618BF042EA8A06C94B566412A7A /* pb_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E052E19761060467DB062D60D88F5536 /* SDStatusBarOverriderPost9_3.m in Sources */ = {isa = PBXBuildFile; fileRef = AD7C3AE346CDF47C559CAA1E29D38819 /* SDStatusBarOverriderPost9_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E1355ABFA24FFFE7788FFC23A0E5543D /* FIRMessagingSecureSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 67D20FEE4726CCB26A931435C6F7F8D6 /* FIRMessagingSecureSocket.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E1797B933E4A716E831F34EFC24F2A18 /* FIRInstanceIDStringEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 24FEA1649F859C025807618A170C83B1 /* FIRInstanceIDStringEncoding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E1C7D68DBCE3516AFDBB93D344E4710D /* BonMot-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0055556FD5940D94B5719D2CE306ED83 /* BonMot-dummy.m */; }; + E20902716A8AA163A00FC6FE3817D4C1 /* FIRAppAssociationRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0245E1DD96C5A71E0976E257585FB875 /* FIRAppAssociationRegistration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E237EA812A181AA46ABC963AC29854A5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + E27438C8E65CF4DAC905C6026EBACC35 /* FIRInstanceIDLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = B348867894A4CE1D01EE3407670282AA /* FIRInstanceIDLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E2B5FF0AD096653DA71FEF1BBDC6233B /* ja.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0F5EF93A5BE453909C31B9C6554C95CD /* ja.lproj */; }; + E2C7E5A5A237425DA4C72EFF01475076 /* FIRMessagingUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D7DEB68026091907EB2EBB5D82C47A00 /* FIRMessagingUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E2E71589715B273DE6163D5FB435592C /* SDStatusBarOverriderPost10_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 1997495D70A0AFDD3D4437EFFABE3048 /* SDStatusBarOverriderPost10_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3A6BE04CAE18910FF90BC707A1B586E /* TextAlignmentConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5112CE97A821E9C641D75D1ADAC3EB32 /* TextAlignmentConstraint.swift */; }; + E5C352E6C1B3288A651344F557E2A10B /* AdaptiveStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E57EB3CB3312081676A46F7238B24 /* AdaptiveStyle.swift */; }; + E75E3A02BC9CCB56D1671F7FDCB1D543 /* GPBRootObject.h in Headers */ = {isa = PBXBuildFile; fileRef = BB5DFE1F01AFD7800F073ECA808AD019 /* GPBRootObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E78643D19759C84B84FA5C437DD5C285 /* Tracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD6721E414F5E4895627210AFB5397AC /* Tracking.swift */; }; + E79E53BD4BED86182EE57B0E7D1FB563 /* Composable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D93E1401B7CC5204F8F2112E6F2DF1A /* Composable.swift */; }; + E851CD56878C963DD7E0CD660FBE4D22 /* FIRMessagingCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 986EF3488689CACCCB183285A1909D6A /* FIRMessagingCodedInputStream.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E86C0147FE8704C88040B0AFEF4E7648 /* FIRInstanceIDTokenOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F5FE5A0393B7EA11DA9DBF03DDF5479 /* FIRInstanceIDTokenOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E88203FD8E2B01EB71219367D94608D0 /* FIRInstanceIDDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C8877C44A2A9CEF55FFA4B756AB34A /* FIRInstanceIDDefines.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E88F998AF2E3FABE07308B1454182029 /* FIRInstanceIDCheckinStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 0904254547F200171C92FAE60BF75E4B /* FIRInstanceIDCheckinStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E914909867188AF11D12A4292BBC9729 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 8942E740881A6372C900E36D68EAF4CB /* GPBCodedOutputStream.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E93C17002FD7C60CDD5B227371E6AE34 /* UIWindow+RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A6E8BEA17526E69B7E7C440D290E2 /* UIWindow+RootViewController.swift */; }; + E985433DB346442DDCB5F6E16CE7D280 /* FIRMessagingRemoteNotificationsProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 7240263E6AB16234AD51BABC7BEDBFD0 /* FIRMessagingRemoteNotificationsProxy.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E98CBA7CFCF3D96C5B50770A4D3517B5 /* FIRMessagingPacketQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F9E4B9D5FF21ED1F4AB75BA5BA13598 /* FIRMessagingPacketQueue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EA4C0FEE83B95FA4CBD6A1C7A1041CCA /* GPBProtocolBuffers.h in Headers */ = {isa = PBXBuildFile; fileRef = 789045C4CD88187B1C8B6952AD65877D /* GPBProtocolBuffers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EB3DC0691CBB0AF117F1D9D442FA67AA /* FIRInstanceIDTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 661D315940B1DDA7A83242BBBB7CFCA3 /* FIRInstanceIDTokenManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EB9352F06FF1E5906D9D91135967ABB8 /* FIRMessagingPubSub.m in Sources */ = {isa = PBXBuildFile; fileRef = 949C61608ACEFB9BB47A141E428D5CED /* FIRMessagingPubSub.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EC29582AC7D6FAE74A58A4795B136544 /* pt.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0172526E6D3CEFD172AD72474B7F1B03 /* pt.lproj */; }; + EC85906F2F06B19325232E7A96846CD3 /* OHHTTPStubsMethodSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = B0DF923FAF38D4B7E93295F4F7B7E252 /* OHHTTPStubsMethodSwizzling.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EF6D8F4A474E5287ABFAE4449F45C827 /* GtalkCore.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D36157D372B866FB49CE4288D881E3 /* GtalkCore.pbobjc.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EFE7887C3624E7E6BA06AECB489778FE /* NSError+FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E542A623F5A954B3F4D243CF8A4FB46 /* NSError+FIRInstanceID.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F2C4A6F7AC480DEFAE6217C46C05E974 /* GPBExtensionRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF32B5609DBC1BE477D33A94686964D /* GPBExtensionRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F36D0E75366326FACC9EB8DE7F4F98F4 /* GULAppEnvironmentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C3BE33C9694478A1505C09DAF4276BAA /* GULAppEnvironmentUtil.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F387A6A0B4F0712AB31A31AF06E1437D /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FA78D05699B3A7B758DCA452BE2C72E /* MessageUI.framework */; }; + F4D84858653EFDD2A8738A28176A44E4 /* FIRMessagingRmqManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 92F4855C80835F853383873CD1CB78B4 /* FIRMessagingRmqManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F53A883BACBEF618EB01165812EB60A8 /* FIRLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 7902953F39F914B13DAD07D6C494973D /* FIRLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F56B615204B36C3D1287663301D9ED63 /* AttributedStringTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3D53C87F3183ECB9828E9F2CC13CEF /* AttributedStringTransformation.swift */; }; + F5770C14010A6EA5DDF6D28111858B75 /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D735903962EFF3FC6A7517312F923CA /* FIRDependency.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F58012B0BEE8E73287F2A68FEDAD92B2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + F5A597E46D8296D2C414626E7F99C0EF /* FIRInstanceID_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F4E12C03F40438969454920C49D2013 /* FIRInstanceID_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F5DC2F62DE6E7D1D2166347768660F62 /* FIRInstanceIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F64FB46C163A2D7EEDD531525ED4A3E /* FIRInstanceIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F628B678C1D14102D5A6B8E8A369F7FD /* FontFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF280833555D9A6C3AB807C1BBEF193 /* FontFeatures.swift */; }; + F6F184A43AABC119977DF12AD2ED2053 /* Pods-PRODUCTNAME-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F63F7236794D312ACB1F32E2BE55CA4 /* Pods-PRODUCTNAME-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F6FF11572A5F8C02E4BA95CD335737E6 /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 809A9FA0958DAAB72D85475C1510B28C /* Api.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F751BBA11B2C9DB683D3FAC54D1B54EC /* GtalkExtensions.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = D5EB134AFDFBA28F3347C088E94F3AA1 /* GtalkExtensions.pbobjc.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F7CA527CFEF6E3DE6466C6D66D138346 /* FIRMessagingLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1500A31AAD61B6B55D1541CEC1F8B821 /* FIRMessagingLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F8E578B6F9EE4FDDEDF54894A8FCD15C /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FA9AF149F192E34E86DF398F93B6819 /* Tab.swift */; }; + F9956CE423EE435E6B36C133CDD5D27B /* CGFloat+DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF40060DC0344F915D924D3DC88F272D /* CGFloat+DeviceSize.swift */; }; + F9A8B355EC256F8B149021EB7C0F8998 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 8487A57EC520F91735649B13CF1455E4 /* FIRInstanceIDCheckinPreferences+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F9B80E71A9F0D909B1F73CCD753CF53B /* FIRBundleUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F6CAA436B21A9F893735228C041394 /* FIRBundleUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + FBA2DE155485C184B1D2D04B60B5F4F0 /* Swiftilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 016ABA6E4EC051693A5A08A27FAAA7DC /* Swiftilities-dummy.m */; }; + FC6AFA3387CA425C566B007F0EA9B9A9 /* FirebaseMessaging-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C9AE3F8C3C621FD1D0196F941D21A520 /* FirebaseMessaging-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FC9D03E94B1D4725AAA52ED0AFD5463F /* FIRInstanceIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 3739B5667A1C1B8452C08E5FB55014E5 /* FIRInstanceIDTokenStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FCEF602D4650E2F192CE13FE12DE83CE /* HairlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9435CEF7CA7BCE866E215F71262E51F6 /* HairlineView.swift */; }; + FD8EAE65C4C2FC32FE51494D63D4D180 /* KeychainAccess-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F140B1E39A706719A3E80EF3EE95186D /* KeychainAccess-dummy.m */; }; + FF1D8B1CA0865B7484F0874C6517D3CD /* Timestamp.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FDE57075083813209769DB1ECBA097C /* Timestamp.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FF7B4E979DC08115710FD5CF868DFABF /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 38337959621A4D9065BD17ACB25371AD /* Wrappers.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 085642005FA342665658867CF888B052 /* PBXContainerItemProxy */ = { + 02B643491EF1939B6406629306F2675E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 56C65DE44367A2F21D49CA08AFC9FB3B; - remoteInfo = Crashlytics; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; }; - 0B3D5FE4B66C1AA4786B9173C45FF5AB /* PBXContainerItemProxy */ = { + 08148E3EFA12C37CE29E49C3C7EF9167 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = EBD7E7BCA2F0D326BAD8C79D06958BDF; - remoteInfo = OHHTTPStubs; + remoteGlobalIDString = 1E798429DCFA7906F6625CCFC1088744; + remoteInfo = SwiftGen; }; - 107F5858160D61E0A3DA5D8722578633 /* PBXContainerItemProxy */ = { + 0C1025B53BD27B110B05E793A41AAC91 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 2C73C7C87E96DD68B751D61C1033C498; - remoteInfo = BonMot; + remoteGlobalIDString = D372E53E2E8FEAA06A0439FB85E65767; + remoteInfo = FirebaseAnalyticsInterop; + }; + 0E252FBA5043E82AE7E96DA6EB172D5A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 148469CADF8690152BAB10A58272A43F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 470FE31978DC918618A329D8B55C85FF; + remoteInfo = Protobuf; + }; + 1A12587DD794CA9955F23A75370F8EAD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7C4F2B07D36F87501AA418B0A2B9B20; + remoteInfo = Swiftilities; + }; + 1BF24697EA008F1406020E754EF90367 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 470FE31978DC918618A329D8B55C85FF; + remoteInfo = Protobuf; + }; + 1F2EFDBE486B46D9BB0ACA670DCE64E5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A3282A5B2437E609EEB85861D7ECE717; + remoteInfo = AppCenter; + }; + 1FDC68635BD8EB1847D7ABA3BDED5D08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D372E53E2E8FEAA06A0439FB85E65767; + remoteInfo = FirebaseAnalyticsInterop; }; - 129F9FCC6AD4F059B7703A766CAA819E /* PBXContainerItemProxy */ = { + 2643B7A0DCE050B7ED6CFA33DA0F6891 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = CCAB7541106C9A08F37141B4E6BABE82; + remoteGlobalIDString = 615C831BCE925ED486B225B87E44926D; remoteInfo = KeychainAccess; }; - 17BAAF8271678B85C41D37005E6590DE /* PBXContainerItemProxy */ = { + 265B4CB516E1900A62F53357B2801D7D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = B3D97E5DFD9D826348C9FD6225F76AC7; - remoteInfo = Sourcery; + remoteGlobalIDString = 470FE31978DC918618A329D8B55C85FF; + remoteInfo = Protobuf; }; - 26E5945A14D4DB45F770936B3EFFC598 /* PBXContainerItemProxy */ = { + 2871C78E72BACE3957C7839A26C5C9E2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = B3D97E5DFD9D826348C9FD6225F76AC7; - remoteInfo = Sourcery; + remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D; + remoteInfo = Alamofire; }; - 2B0538B0EAB1AB09A690575AAEB41DCC /* PBXContainerItemProxy */ = { + 2A7CCB51109B88316A5FC993FB897CEB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 225EC5F2F324BAAC968D55C764D70D1E; - remoteInfo = SwiftGen; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + 2E46EEE58DA8EA73341280992D1C5D13 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0E41540D6862472ED7F2FA11669BE1F; + remoteInfo = Crashlytics; }; - 3916A6D013B15592701353B07264AEDC /* PBXContainerItemProxy */ = { + 2E884F9A0CD78CCADB89B607F8BDB639 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 2C73C7C87E96DD68B751D61C1033C498; + remoteGlobalIDString = 4C48FB7D363771FBD71AB44C090CB586; remoteInfo = BonMot; }; - 3A1A8050DFC1EA428BB3F414DF269AA1 /* PBXContainerItemProxy */ = { + 3103E425B0EDFA9736C768A7D3E015B9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A983A2D06C5B6AA3D6ABA5CCC0A16725; + remoteInfo = OHHTTPStubs; + }; + 33807B5A769F0C36650DF5EE9C76AB54 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D8229B0397AE8C2F7C11B3F9EFC9362; + remoteInfo = Sourcery; + }; + 39C2E1ACB757D961A3B5FA5055DBDB7A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + 3DB056970030F95365323DB7D483F0E4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = ABB048B191245233986A7CD75FE412A5; + remoteInfo = Fabric; + }; + 43F7D12D0CBAC174D94F813DCDD5FCB4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 19F29DF95D2D1863DFA4C4BE96A51134; + remoteGlobalIDString = E7C4F2B07D36F87501AA418B0A2B9B20; remoteInfo = Swiftilities; }; - 43BDBE6C7740556BACD88519F785BC8B /* PBXContainerItemProxy */ = { + 47C1327AD0E022A8CAD8A8A249109E10 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 9297674709A684A35778E46A8DD2FBF1; - remoteInfo = SwiftLint; + remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D; + remoteInfo = Alamofire; }; - 4994FF095EEECB5DC82D47D24221AF6B /* PBXContainerItemProxy */ = { + 4809F369638E77D13FBA5FDDC4B279F0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 59FF3124354BB8932D3D16CEF7473837; - remoteInfo = SimulatorStatusMagic; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; }; - 49F3EAF1D7395F993FB1E1379E25E6D5 /* PBXContainerItemProxy */ = { + 4C0638D0D195A9000851F687C36E3AF2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5727E61F2F741F9002936940674C2C4C; - remoteInfo = Instabug; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; }; - 4C59DDA516F65563F41EAC3E60B1D180 /* PBXContainerItemProxy */ = { + 4C4B6E49A1CB5F547EF7EDA8A2894B2E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = B3D97E5DFD9D826348C9FD6225F76AC7; + remoteGlobalIDString = 4D8229B0397AE8C2F7C11B3F9EFC9362; remoteInfo = Sourcery; }; - 4D08AA0D173311D87B23B36F15F881C9 /* PBXContainerItemProxy */ = { + 5377C294E50C7447C27E7C2D9D0BC8C4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = CCAB7541106C9A08F37141B4E6BABE82; - remoteInfo = KeychainAccess; + remoteGlobalIDString = C0E41540D6862472ED7F2FA11669BE1F; + remoteInfo = Crashlytics; }; - 62BF750024C73BD63BBB5D26CAE963FC /* PBXContainerItemProxy */ = { + 543BCBF2DF409AB1D8FBE0BB138681A9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 56C65DE44367A2F21D49CA08AFC9FB3B; - remoteInfo = Crashlytics; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 5576D78AFE2208B1EEFB5282D84D1F08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = ABB048B191245233986A7CD75FE412A5; + remoteInfo = Fabric; + }; + 5802AA2B78C7A3E6CF58C77D762D71E9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B593490A33943610DC035C394E10D07A; + remoteInfo = Instabug; }; - 6603F971020D3767F8FB7DE1933C5576 /* PBXContainerItemProxy */ = { + 5B756F4043C0BF271158008CDED79D84 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 8D3A1239E052634147734F80F823491B; + remoteGlobalIDString = 4607A9D579EE69C57F52971930107170; remoteInfo = Anchorage; }; - 732E977BD587A7949D21277805A7F263 /* PBXContainerItemProxy */ = { + 61CD1DC5DB1618415917A6B6B148544A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 59FF3124354BB8932D3D16CEF7473837; - remoteInfo = SimulatorStatusMagic; + remoteGlobalIDString = 4C48FB7D363771FBD71AB44C090CB586; + remoteInfo = BonMot; }; - 88B6355FFB5EE4E71FC2376CD9BD082A /* PBXContainerItemProxy */ = { + 635675962B01177CB052EE57060E9175 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = DACB20301113D16B776F458649C04D75; - remoteInfo = GoogleAnalytics; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; }; - 8AFC34FD9107620797D08F617071FE3A /* PBXContainerItemProxy */ = { + 650053CB0020B8878A2D404A11BA8849 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = CCAB7541106C9A08F37141B4E6BABE82; - remoteInfo = KeychainAccess; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; }; - 8F1AB109557454819AC6FB736B4C2EC8 /* PBXContainerItemProxy */ = { + 66BF61E910A9B80A8316776974C2BB95 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 2C73C7C87E96DD68B751D61C1033C498; - remoteInfo = BonMot; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; }; - 95CBF8E05B1C8C21922F46385C8913AD /* PBXContainerItemProxy */ = { + 689919C1E5546B4C5075358DC52F3565 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 9297674709A684A35778E46A8DD2FBF1; - remoteInfo = SwiftLint; + remoteGlobalIDString = 5895B432FE4D2F6826C8FF25A09DB6D2; + remoteInfo = FirebaseMessaging; }; - 977879763DF2C70A04DACC092D0BCF03 /* PBXContainerItemProxy */ = { + 689D82AE9C6AAEF561CBC45F0C3F37D8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = E4C40E20827836CD754239D105918E4F; - remoteInfo = Alamofire; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; }; - 9C240FDBE0F83173CE9EFAD71689332D /* PBXContainerItemProxy */ = { + 6ECBB905773B62DD8276A7843DE12298 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 225EC5F2F324BAAC968D55C764D70D1E; - remoteInfo = SwiftGen; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 73FE5A0BD5D3991167C7C54DD4D446DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 75EA1E73941199F90021A0EBD5ED4264 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; }; - A33EA930646776DF7C00CC7A87A026B5 /* PBXContainerItemProxy */ = { + 79EEB88422FF194A2426408E288FCAA8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 8D3A1239E052634147734F80F823491B; + remoteGlobalIDString = 4607A9D579EE69C57F52971930107170; remoteInfo = Anchorage; }; - A85E0153EF5D7727753CFA1B149A4B2F /* PBXContainerItemProxy */ = { + 7A591D0D32FC2DC7C5953B14551C8425 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 92AABBA7207468A376E84C3CAB584DF1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7C4F2B07D36F87501AA418B0A2B9B20; + remoteInfo = Swiftilities; + }; + 93FC40FACD2A3CAE5B749D36454B21BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 95B892EE3C9D4BCC89AA02E77558C5CF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 225EC5F2F324BAAC968D55C764D70D1E; + remoteGlobalIDString = 1E798429DCFA7906F6625CCFC1088744; remoteInfo = SwiftGen; }; - AC68A476D2DE351C94651D7AA9E67190 /* PBXContainerItemProxy */ = { + 9DE5315A218DF3035FAB4B2C9C4D11CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D8229B0397AE8C2F7C11B3F9EFC9362; + remoteInfo = Sourcery; + }; + A0D8BA7AAAA886E42762C6361B9E93C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + A57D1B3D3A7F6453569CBAD3F3B57B2B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + B269AA35A62F09500537A4BA3BFB44C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 615C831BCE925ED486B225B87E44926D; + remoteInfo = KeychainAccess; + }; + B5EC11065BDE7CEAB67D207F576271FB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = E4C40E20827836CD754239D105918E4F; + remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D; remoteInfo = Alamofire; }; - B5A935E1584EE3E560B5CE58A9AEC03B /* PBXContainerItemProxy */ = { + BA9CC50F725C6CC259A91562DDF28E28 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = E28CCDDA0BCE0276CB18E6AE6E42CC00; - remoteInfo = Fabric; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + BAE33B3D752C070CD5F2887D4F50B516 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + BBA3C65F4427758819F8FE0EB02A684A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1E798429DCFA7906F6625CCFC1088744; + remoteInfo = SwiftGen; + }; + BE218348DB050D18EB6D52F098627920 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; + remoteInfo = SwiftLint; }; BF2E36C9AB9868362ECE4F7D15CA684C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = E28CCDDA0BCE0276CB18E6AE6E42CC00; + remoteGlobalIDString = ABB048B191245233986A7CD75FE412A5; remoteInfo = Fabric; }; - D11C6E9AF90019984BFAE36131AD4336 /* PBXContainerItemProxy */ = { + C6B51788BF5B5F1CA75F34172EAC8C66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = E28CCDDA0BCE0276CB18E6AE6E42CC00; - remoteInfo = Fabric; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; }; - DF1614AEEACBB691AA7E18F35946DA0E /* PBXContainerItemProxy */ = { + C80C2AF874999BC32CD68D52CF8B6442 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = E4C40E20827836CD754239D105918E4F; - remoteInfo = Alamofire; + remoteGlobalIDString = 4607A9D579EE69C57F52971930107170; + remoteInfo = Anchorage; }; - E8AB0247FAB907CD91CA25733C2B8A28 /* PBXContainerItemProxy */ = { + CC51CF93141CEA0C62DE97225C0BC04E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 19F29DF95D2D1863DFA4C4BE96A51134; - remoteInfo = Swiftilities; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; }; - EF2E574032F4C13F51E21EA063963A2C /* PBXContainerItemProxy */ = { + CCD653DB7DAA28F82561ABBA8580BADE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5727E61F2F741F9002936940674C2C4C; - remoteInfo = Instabug; + remoteGlobalIDString = 95F19093D340358F7EE721EC01F43355; + remoteInfo = SimulatorStatusMagic; }; - F0FC023A7FAA25251FF855FDF3DF3B78 /* PBXContainerItemProxy */ = { + D10A23904F9F6203C441116CC0642596 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = DACB20301113D16B776F458649C04D75; - remoteInfo = GoogleAnalytics; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; }; - F1A311C6FA88CF80A388ED605152118B /* PBXContainerItemProxy */ = { + D9CCC0B18E86FDC85771011139ACDCD4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 8D3A1239E052634147734F80F823491B; - remoteInfo = Anchorage; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; }; - F2ABE20F2506CF359EEE59DB74D89683 /* PBXContainerItemProxy */ = { + DB41FC5EB5ED2499B0E89BB46AA4359B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 9297674709A684A35778E46A8DD2FBF1; + remoteGlobalIDString = 615C831BCE925ED486B225B87E44926D; + remoteInfo = KeychainAccess; + }; + DCD1C96ECC57BB8FC7BB0C12A709B9F1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; remoteInfo = SwiftLint; }; - F84E9C29E13B34282E85294A32AE6BE4 /* PBXContainerItemProxy */ = { + DEF897143670388E42D9901AD7FECCDC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 19F29DF95D2D1863DFA4C4BE96A51134; - remoteInfo = Swiftilities; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + DF4A594B4218CCA9EF0D5B89B5EFB551 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A3282A5B2437E609EEB85861D7ECE717; + remoteInfo = AppCenter; + }; + DF66A2F4782D1A0979660E315CF32196 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; + remoteInfo = SwiftLint; + }; + E327328558089D481E112C8A4A506DE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + E50E5C34A42ACE328C4D101E74D0E458 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5895B432FE4D2F6826C8FF25A09DB6D2; + remoteInfo = FirebaseMessaging; + }; + E9C5672F0CD0FA063A46323C4AC136D2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 95F19093D340358F7EE721EC01F43355; + remoteInfo = SimulatorStatusMagic; + }; + F08459BC4BC97915AAF676A70BA1044E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5895B432FE4D2F6826C8FF25A09DB6D2; + remoteInfo = FirebaseMessaging; + }; + F3A392E1ED6D4068A572BD13DC958074 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D372E53E2E8FEAA06A0439FB85E65767; + remoteInfo = FirebaseAnalyticsInterop; + }; + F7B77B6FF52752D1C86E594584C3D247 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + F83820FC705E1ACB652B680E9ED10441 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C48FB7D363771FBD71AB44C090CB586; + remoteInfo = BonMot; + }; + FBBD79508378F74FDD48FDE8FBD95CA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + FC1D9ED47627FC05FEF6B4B3B5CDB53C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FCD9915FE83842AE0201096155515772; + remoteInfo = "AppCenter-AppCenterDistributeResources"; + }; + FCB8621B4850804581799AA75D809CD9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + FE3AF2118BF9BD4601F3A147DBC26D4C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B593490A33943610DC035C394E10D07A; + remoteInfo = Instabug; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0344F233E115ED3F7D904DC23394C60C /* HairlineView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HairlineView.swift; path = Pod/Classes/HairlineView/HairlineView.swift; sourceTree = ""; }; - 03BB3A2B2382C9AECA1345DF10758FF7 /* IBGBugReporting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGBugReporting.h; path = Instabug.framework/Headers/IBGBugReporting.h; sourceTree = ""; }; - 04E11008993CDF01137A6258C64C7633 /* FABAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FABAttributes.h; path = iOS/Fabric.framework/Headers/FABAttributes.h; sourceTree = ""; }; - 04FA80AC5B62CDAB5253E08409C0D0B9 /* TextAlignmentConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextAlignmentConstraint.swift; path = Sources/UIKit/TextAlignmentConstraint.swift; sourceTree = ""; }; - 0844167EF0604BA510C035ACDF453F20 /* NSURLRequest+HTTPBodyTesting.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSURLRequest+HTTPBodyTesting.m"; path = "OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.m"; sourceTree = ""; }; - 08B38982F150A6862B8AD2A945D9B407 /* ContextualAlternates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContextualAlternates.swift; path = Sources/ContextualAlternates.swift; sourceTree = ""; }; - 08D058A0428C1C703F302390940EB70D /* IBGLog.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGLog.h; path = Instabug.framework/Headers/IBGLog.h; sourceTree = ""; }; - 08FEAA71D51B643545C21B77DC4D28DD /* Image+Tinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Image+Tinting.swift"; path = "Sources/Image+Tinting.swift"; sourceTree = ""; }; - 095ABB58DBD99D3A10453F530368A5F0 /* Composable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Composable.swift; path = Sources/Composable.swift; sourceTree = ""; }; - 0AD288A8A84E421BED98CFA78BA83CAD /* Tab+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Tab+Adaptive.swift"; path = "Sources/UIKit/Tab+Adaptive.swift"; sourceTree = ""; }; - 0B23ECB1A1FC9AA01FEB7FABD6E284E1 /* IndexPath+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "IndexPath+Extensions.swift"; path = "Pod/Classes/TableViewHelpers/IndexPath+Extensions.swift"; sourceTree = ""; }; - 0B2E6AF6F88FDD1CE6C631AD781A61C9 /* OHHTTPStubsMethodSwizzling.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsMethodSwizzling.h; path = OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.h; sourceTree = ""; }; - 0C509062B34F03EFFC01A0972C94C56B /* OHHTTPStubsMethodSwizzling.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsMethodSwizzling.m; path = OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.m; sourceTree = ""; }; - 0CA525AAB4893235D02EA212CA8407AE /* Compatibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatibility.swift; path = Pod/Classes/Compatibility/Compatibility.swift; sourceTree = ""; }; - 0D5FCA72714F0B65331606F33C76F18A /* Instabug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Instabug.framework; sourceTree = ""; }; - 0D9B5EA89BF66F54C9437D2204EC0D69 /* UIView+Lookup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+Lookup.swift"; path = "Pod/Classes/Forms/UIView+Lookup.swift"; sourceTree = ""; }; - 0E460FE658668EC518CCCB65C4F75F33 /* SDStatusBarOverriderPost9_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost9_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost9_0.m; sourceTree = ""; }; - 0EB51FACE363CF08AD66B491366ECCA6 /* AcknowledgementViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementViewController.swift; path = Pod/Classes/Acknowledgements/AcknowledgementViewController.swift; sourceTree = ""; }; - 111EE320E7BC5B51DA0B08B5F6CCCAE2 /* ANSCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ANSCompatibility.h; path = iOS/Crashlytics.framework/Headers/ANSCompatibility.h; sourceTree = ""; }; - 11D7CFFD8553B55C3A3B2272283373A6 /* FontInspector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FontInspector.swift; path = Sources/FontInspector.swift; sourceTree = ""; }; - 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 13DDEF6C866280C73475A52AC509488F /* AdaptableTextContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptableTextContainer.swift; path = Sources/UIKit/AdaptableTextContainer.swift; sourceTree = ""; }; - 163CBECB08FD3C96E47CB9147E7FB3EB /* Crashlytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Crashlytics.h; path = iOS/Crashlytics.framework/Headers/Crashlytics.h; sourceTree = ""; }; - 16618C3BC05BC3E526CD791AA381BFB3 /* UIView+KeyboardLayoutGuide.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+KeyboardLayoutGuide.swift"; path = "Pod/Classes/Keyboard/UIView+KeyboardLayoutGuide.swift"; sourceTree = ""; }; - 169E0A2C66830CE4D025F55BF0B70D78 /* SDStatusBarOverriderPost10_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost10_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost10_0.h; sourceTree = ""; }; - 171475FCE61CF50AA00728DC54688438 /* TintedButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TintedButton.swift; path = Pod/Classes/TintedButton/TintedButton.swift; sourceTree = ""; }; - 18A0C90ABF64C64D2F8388FD400A65C3 /* LifecycleBehaviorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LifecycleBehaviorViewController.swift; path = Pod/Classes/Lifecycle/Framework/LifecycleBehaviorViewController.swift; sourceTree = ""; }; - 1C61F5CB85EBA2E536ABB3FACB92C14D /* IBGSurvey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGSurvey.h; path = Instabug.framework/Headers/IBGSurvey.h; sourceTree = ""; }; - 1CCAE7D4A6245F5F4C44F739DBC1DE61 /* Special.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Special.swift; path = Sources/Special.swift; sourceTree = ""; }; - 1D90E1557A97E8534260AE63FB8122C2 /* CGSize+DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CGSize+DeviceSize.swift"; path = "Pod/Classes/DeviceSize/CGSize+DeviceSize.swift"; sourceTree = ""; }; - 1FA9640C042660F51CFBC1B9D754150A /* OHHTTPStubs.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubs.m; path = OHHTTPStubs/Sources/OHHTTPStubs.m; sourceTree = ""; }; - 2448D385AC85F37AF99BFC03ACAAB403 /* Validation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Validation.swift; path = Source/Validation.swift; sourceTree = ""; }; - 24E6EDD19D24D9E3522A79BF5F36D8F2 /* StringStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StringStyle.swift; path = Sources/StringStyle.swift; sourceTree = ""; }; - 24EBA9AD10434F4F0FA3C89E27567DDA /* EmbeddedTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmbeddedTransformation.swift; path = Sources/UIKit/EmbeddedTransformation.swift; sourceTree = ""; }; - 2576CF28FDBBF7E2E16AD4DC47FE9EE3 /* Anchorage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Anchorage.modulemap; sourceTree = ""; }; - 276D6C93C6813A9140365BF3CBD94A65 /* NavBarHairlineFadeBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NavBarHairlineFadeBehavior.swift; path = "Pod/Classes/Lifecycle/Behaviors/Nav-Bar-Hairline-Fade/NavBarHairlineFadeBehavior.swift"; sourceTree = ""; }; - 2814252E46C1C3D835FC3766FA37E50B /* IBGSurveys.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGSurveys.h; path = Instabug.framework/Headers/IBGSurveys.h; sourceTree = ""; }; - 287203EA6EB5EB516A7B9DE8645F0403 /* OHHTTPStubs+NSURLSessionConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubs+NSURLSessionConfiguration.m"; path = "OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m"; sourceTree = ""; }; - 289F895A731229C94D7D07DFD3480E56 /* Swiftilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Swiftilities-umbrella.h"; sourceTree = ""; }; - 2927977169D5E8824B1B0F49F29DCDB7 /* IBGFeatureRequests.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGFeatureRequests.h; path = Instabug.framework/Headers/IBGFeatureRequests.h; sourceTree = ""; }; - 29ABD7B829A0C25AC36C7EDE2458B4C1 /* BonMot-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BonMot-Info.plist"; sourceTree = ""; }; - 29EF59452D21EA57CF6157AFAE72F043 /* Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig"; sourceTree = ""; }; - 2C2CF3EDAF2544698EB98DE619346902 /* Pods-Services.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.appstore.xcconfig"; sourceTree = ""; }; - 2C90242292A7BE097ED8F53F6314A670 /* OHPathHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHPathHelpers.m; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m; sourceTree = ""; }; - 2DDC6450754D0AB3B48A89969F7CCE4C /* GAIEcommerceProduct.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAIEcommerceProduct.h; path = Sources/GAIEcommerceProduct.h; sourceTree = ""; }; - 2E0B0149FAAF2D1D209AED840BEF43CC /* KeychainAccess-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "KeychainAccess-Info.plist"; sourceTree = ""; }; - 2E8DEEC8D4E92C46491262BFEFD046CC /* InstabugCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = InstabugCore.h; path = Instabug.framework/Headers/InstabugCore.h; sourceTree = ""; }; - 2F6BE75B39581AB2EE6B4DFDF846086D /* Pods-Services.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Services.modulemap"; sourceTree = ""; }; - 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Instabug.xcconfig; sourceTree = ""; }; - 2FB8C1752861586CF1E04E22B05009B9 /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m"; sourceTree = ""; }; - 301105F4D7338338C59D0195933FA755 /* KeychainAccess.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = KeychainAccess.framework; path = KeychainAccess.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3198255E8CC28000CEAA0676F48D77BA /* OHHTTPStubs-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "OHHTTPStubs-Info.plist"; sourceTree = ""; }; - 330CCA593DDAE935D8E8573A0728E931 /* Tracking+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Tracking+Adaptive.swift"; path = "Sources/UIKit/Tracking+Adaptive.swift"; sourceTree = ""; }; - 3411EC3BF6C45108122770A9510E4DAF /* Anchorage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Anchorage-prefix.pch"; sourceTree = ""; }; - 362EF0199AD907539D86EBEF1DE6556C /* StyleableUIElement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StyleableUIElement.swift; path = Sources/UIKit/StyleableUIElement.swift; sourceTree = ""; }; - 3639D14F3C07D749FB3063E068487445 /* NavTitleTransitionBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NavTitleTransitionBehavior.swift; path = "Pod/Classes/Lifecycle/Behaviors/Nav-Bar-Title-Transition/NavTitleTransitionBehavior.swift"; sourceTree = ""; }; - 3642AF4C5ABB338945962F45503807EE /* GAIEcommerceFields.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAIEcommerceFields.h; path = Sources/GAIEcommerceFields.h; sourceTree = ""; }; - 3749D57AF44719F99E7573D0EF50F406 /* CurveProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CurveProvider.swift; path = Pod/Classes/Math/CurveProvider.swift; sourceTree = ""; }; - 3883E78F24323AF243E39A35CED0B383 /* Pods-PRODUCTNAME-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PRODUCTNAME-frameworks.sh"; sourceTree = ""; }; - 39279866EC1760AFEE29D2DEEED6C856 /* ResponseSerialization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResponseSerialization.swift; path = Source/ResponseSerialization.swift; sourceTree = ""; }; - 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Swiftilities.xcconfig; sourceTree = ""; }; - 3A3E0BA8DC4603ECFD3151F8B3C81598 /* SessionManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionManager.swift; path = Source/SessionManager.swift; sourceTree = ""; }; - 3D44924F1DBF16C7E8D7BE1A271DFA34 /* Pods-Services-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Services-Info.plist"; sourceTree = ""; }; - 3E41B0F9E8C162A676783159D2E6BB11 /* UIImage+Tinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIImage+Tinting.swift"; path = "Pod/Classes/ImageHelpers/UIImage+Tinting.swift"; sourceTree = ""; }; - 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Anchorage.xcconfig; sourceTree = ""; }; - 3F338A55DD7E095C1009887CED6DC4AC /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/MessageUI.framework; sourceTree = DEVELOPER_DIR; }; - 3FA96E21CB7C709D604705CC1A70427A /* Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig"; sourceTree = ""; }; - 4096AE254E9EB97D97FD6EB20D605B6A /* ServerTrustPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServerTrustPolicy.swift; path = Source/ServerTrustPolicy.swift; sourceTree = ""; }; - 40F8BD0AE7464E998720C28C143621BE /* KeychainAccess.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = KeychainAccess.modulemap; sourceTree = ""; }; - 412B8AA2EB07D89E85469CB8B5773CC3 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Source/Result.swift; sourceTree = ""; }; - 423575D637674B034C086A88A750516A /* Swiftilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Swiftilities-dummy.m"; sourceTree = ""; }; - 45DE58670D5CC4C511D327BD0944AA59 /* Tab.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tab.swift; path = Sources/Tab.swift; sourceTree = ""; }; - 467A292772A289D715C80B2C2CB65115 /* Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; sourceTree = ""; }; - 473B67F1C327A540855E3FC4CDFA3DEE /* UIStackView+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIStackView+Helpers.swift"; path = "Pod/Classes/StackViewHelpers/UIStackView+Helpers.swift"; sourceTree = ""; }; - 474A11822039E6AA6B471CD830ADD05F /* Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh"; sourceTree = ""; }; - 47B116AABF6F54A2E56D0AA81C893247 /* TableSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableSection.swift; path = Pod/Classes/TableViewHelpers/TableSection.swift; sourceTree = ""; }; - 47CB2C8C52E2A4F6F847C2D4939E36B1 /* BetterButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BetterButton.swift; path = Pod/Classes/BetterButton/BetterButton.swift; sourceTree = ""; }; - 49442838275784AC430968A99E9197D0 /* Pods-PRODUCTNAME.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PRODUCTNAME.modulemap"; sourceTree = ""; }; - 4DEA707B91546820EF3F5255BA544E4E /* GAITracker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAITracker.h; path = Sources/GAITracker.h; sourceTree = ""; }; - 4E340EC5B601C12215D9F8E375C37261 /* Anchorage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Anchorage-dummy.m"; sourceTree = ""; }; - 5086A712A691195906CCBD885DAF44FB /* Timeline.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Timeline.swift; path = Source/Timeline.swift; sourceTree = ""; }; - 5175D0955C66D6BC673461F540D755E6 /* UIViewController+Deselection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Deselection.swift"; path = "Pod/Classes/Deselection/UIViewController+Deselection.swift"; sourceTree = ""; }; - 519CB531B27E0A624D038221B6D26038 /* SimulatorStatusMagic-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SimulatorStatusMagic-prefix.pch"; sourceTree = ""; }; - 53A72D85B745ED549CABA1B2596D6E07 /* AdaptiveStyleTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptiveStyleTransformation.swift; path = Sources/UIKit/AdaptiveStyleTransformation.swift; sourceTree = ""; }; - 5426B4EA8AB7C69CCFB6311BF4008D2F /* SimulatorStatusMagic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SimulatorStatusMagic.framework; path = SimulatorStatusMagic.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 54B8EFB70012E9BEFC2371D3FF24AB1E /* SDStatusBarOverriderPost9_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost9_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost9_3.h; sourceTree = ""; }; - 54C8E02EC8ABE5CF2CA2B3840F75FC8F /* AboutView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AboutView.swift; path = Pod/Classes/AboutView/AboutView.swift; sourceTree = ""; }; - 54CC3A9A9520AF155108F8CE284EB864 /* PlaceholderTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PlaceholderTextView.swift; path = Pod/Classes/Views/Textview/PlaceholderTextView.swift; sourceTree = ""; }; - 582BD27DFB831D016846914FEDC4084D /* BonMot-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BonMot-prefix.pch"; sourceTree = ""; }; - 5922604290D09B15C428A4127852F8D2 /* XMLBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XMLBuilder.swift; path = Sources/XMLBuilder.swift; sourceTree = ""; }; - 5C36B781D279FBC53B84933BBA772A0E /* Pods_PRODUCTNAME.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PRODUCTNAME.framework; path = "Pods-PRODUCTNAME.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 5CB62BF9A996328D3C7FD3E03A32F740 /* Pods-PRODUCTNAME-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-acknowledgements.plist"; sourceTree = ""; }; - 5E43976F0F6BEFD1D8B1A747810E1EB9 /* SimulatorStatusMagic-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SimulatorStatusMagic-Info.plist"; sourceTree = ""; }; - 5F12A1D968B46216AE4EE506629B554E /* FontFeatures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FontFeatures.swift; path = Sources/FontFeatures.swift; sourceTree = ""; }; - 600A0B900A253A3C1175F9E4D95DB5D0 /* SDStatusBarManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarManager.m; path = SDStatusBarManager/SDStatusBarManager.m; sourceTree = ""; }; - 60C2A42E80DFA41030FABD4A88393F4D /* AcknowledgementsListViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementsListViewModel.swift; path = Pod/Classes/Acknowledgements/AcknowledgementsListViewModel.swift; sourceTree = ""; }; - 60E972D817C96D8EEFF0C1423650DDFD /* Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; sourceTree = ""; }; - 61D71EA297A255FC6751524FC2D7AE30 /* SDStatusBarOverriderPost12_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost12_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost12_0.m; sourceTree = ""; }; - 62A0F259EB5E8BF8A9D802020E3C6C2D /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = iOS/Crashlytics.framework; sourceTree = ""; }; - 62AF34195393D64764BB5AE60633CF06 /* AcknowledgementsListViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementsListViewController.swift; path = Pod/Classes/Acknowledgements/AcknowledgementsListViewController.swift; sourceTree = ""; }; - 62FABFF9927EB4903E6F34356FF106F4 /* NamedStyles.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NamedStyles.swift; path = Sources/NamedStyles.swift; sourceTree = ""; }; - 63815B6D30E9C8BAA285DE33797AEF53 /* GAILogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAILogger.h; path = Sources/GAILogger.h; sourceTree = ""; }; - 66BCBFC05E4D8780FD4246F0345294C9 /* Swiftilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Swiftilities-prefix.pch"; sourceTree = ""; }; - 673ABFE194DF7A08FA263E12BAB82F4C /* Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alamofire.swift; path = Source/Alamofire.swift; sourceTree = ""; }; - 67CEC4C18F7EF40BF8EF7C4EA61392DB /* Notifications.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Notifications.swift; path = Source/Notifications.swift; sourceTree = ""; }; - 6850346376F7BEE1EB250B890DCBE0BF /* AnchorGroupProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnchorGroupProvider.swift; path = Source/AnchorGroupProvider.swift; sourceTree = ""; }; - 693EB792331AD6ABD61A27768244D086 /* Answers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Answers.h; path = iOS/Crashlytics.framework/Headers/Answers.h; sourceTree = ""; }; - 694AD7393AED493BB49E808D261B32A7 /* Clamping.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Clamping.swift; path = Pod/Classes/Math/Clamping.swift; sourceTree = ""; }; - 6BC0330C6905084757112A6626DEA435 /* Alamofire.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Alamofire.modulemap; sourceTree = ""; }; - 6C4CA57B497201B0B30CAB96DDE10D16 /* SDStatusBarOverriderPost8_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost8_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost8_3.m; sourceTree = ""; }; - 6C8D7031183605564560F8C005274726 /* IBGChats.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGChats.h; path = Instabug.framework/Headers/IBGChats.h; sourceTree = ""; }; - 6D5D69F8E132528B4DFF162031B38803 /* GAIEcommerceProductAction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAIEcommerceProductAction.h; path = Sources/GAIEcommerceProductAction.h; sourceTree = ""; }; - 6F23572C7CB158962AEB29506087D42A /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h"; sourceTree = ""; }; - 6F7BCF16E3577A7314986934680E4C23 /* Response.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Response.swift; path = Source/Response.swift; sourceTree = ""; }; - 704ACC5578BE8DC6950CC29EA7C1AFE1 /* AttributedStringTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AttributedStringTransformation.swift; path = Sources/UIKit/AttributedStringTransformation.swift; sourceTree = ""; }; - 70668D84A9B3C780A359D0F2B58A1D4B /* LicenseFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LicenseFormatter.swift; path = Pod/Classes/LicenseFormatter/LicenseFormatter.swift; sourceTree = ""; }; - 708747111C024E9A7164DB43F2862C22 /* GAIFields.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAIFields.h; path = Sources/GAIFields.h; sourceTree = ""; }; - 7111D87220CD12D9B160A6B7879E1A7A /* SimulatorStatusMagic.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SimulatorStatusMagic.modulemap; sourceTree = ""; }; - 712AA0B3114BE06914AA73650935B4B3 /* StringStyle+Part.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "StringStyle+Part.swift"; path = "Sources/StringStyle+Part.swift"; sourceTree = ""; }; - 71BC06C450F39A6C28917FDFD2D3D3A4 /* IBGNetworkLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGNetworkLogger.h; path = Instabug.framework/Headers/IBGNetworkLogger.h; sourceTree = ""; }; - 72B5BB3EED5E5C863F41621DD901083C /* Protocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Protocols.swift; path = Pod/Classes/Views/Textview/Protocols.swift; sourceTree = ""; }; - 762B6EA59AD44657FC4F6F155EE84D81 /* Pods-PRODUCTNAME.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.appstore.xcconfig"; sourceTree = ""; }; - 763EA71849BAFD4F80AE0913CD8AEB09 /* Pods-Services.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.develop.xcconfig"; sourceTree = ""; }; - 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SimulatorStatusMagic.xcconfig; sourceTree = ""; }; - 76574677F65789134324FB1D3C925091 /* SDStatusBarOverriderPost12_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost12_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost12_0.h; sourceTree = ""; }; - 76B2C8862CEAB7ED9309B5842CD243A2 /* OHHTTPStubs.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = OHHTTPStubs.modulemap; sourceTree = ""; }; - 76CC1EB38705E8C45784419E12627B8B /* Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig"; sourceTree = ""; }; - 78D61CCC7F7CA3A111C6C359B619EFD6 /* Priority.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Priority.swift; path = Source/Priority.swift; sourceTree = ""; }; - 7B0FA4328DAC940D1CB38E6FBC0DCDD6 /* UIViewController+Lifecycle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Lifecycle.swift"; path = "Pod/Classes/Lifecycle/Framework/UIViewController+Lifecycle.swift"; sourceTree = ""; }; - 7B61F355D3DB41F42478FC6C1F38A450 /* MultipartFormData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartFormData.swift; path = Source/MultipartFormData.swift; sourceTree = ""; }; - 7E363AC19B8D721F73D148E1225011D9 /* IBGReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGReport.h; path = Instabug.framework/Headers/IBGReport.h; sourceTree = ""; }; - 7E61565DBEC973F19175F0B6B4BF9251 /* KeychainAccess-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "KeychainAccess-dummy.m"; sourceTree = ""; }; - 7EA968D668E05238E14773825FCF5CF5 /* GAI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAI.h; path = Sources/GAI.h; sourceTree = ""; }; - 80930814506B3CE5606AA7DED6CBA9B4 /* GradientView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = Pod/Classes/Views/Gradient/GradientView.swift; sourceTree = ""; }; - 828C42D1340C4F63C8F0F9D333CD612A /* SDStatusBarOverriderPost8_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost8_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost8_3.h; sourceTree = ""; }; - 8322C8C3CC5229674C4860D5DADC299F /* OHHTTPStubsResponse+JSON.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "OHHTTPStubsResponse+JSON.h"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h"; sourceTree = ""; }; - 84B709879A680D555D406FEF46B4B386 /* OHHTTPStubsResponse+JSON.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubsResponse+JSON.m"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.m"; sourceTree = ""; }; - 85A6A4A85CADB17311A03BB6003CDC8B /* NSAttributedString+BonMot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+BonMot.swift"; path = "Sources/NSAttributedString+BonMot.swift"; sourceTree = ""; }; - 8616019682F89AF777F1467F9FADF221 /* OHHTTPStubs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubs.h; path = OHHTTPStubs/Sources/OHHTTPStubs.h; sourceTree = ""; }; - 863B364319BA1C8E81DB7F006A9A31BC /* StylisticAlternates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StylisticAlternates.swift; path = Sources/StylisticAlternates.swift; sourceTree = ""; }; - 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alamofire.xcconfig; sourceTree = ""; }; - 88BA0595C84DF09AE03104A4BDD671A8 /* Pods-PRODUCTNAME.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.sprint.xcconfig"; sourceTree = ""; }; - 88E5F6A803FEFEF70F140D44D4DD1CA0 /* Transform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transform.swift; path = Sources/Transform.swift; sourceTree = ""; }; - 89450B8529A81C5B1E75A786D5FABC3D /* Emphasis.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Emphasis.swift; path = Sources/Emphasis.swift; sourceTree = ""; }; - 89E43AF1CEC2C19E8EB86AE3397389EA /* MutableCopying.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MutableCopying.swift; path = Sources/MutableCopying.swift; sourceTree = ""; }; - 8A2B8AA86BCE7F70AAAF10D276187F76 /* BonMot.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BonMot.modulemap; sourceTree = ""; }; - 8A56048850B5EB8CF23F6DAD9C06FBF7 /* Keychain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Keychain.swift; path = Lib/KeychainAccess/Keychain.swift; sourceTree = ""; }; - 8ACDCF9FDA55A7DB7730D6DB537616F6 /* SDStatusBarOverriderPost11_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost11_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost11_0.h; sourceTree = ""; }; - 8B9CD9D4507F0BB5DA2B05A298D3C3AC /* CubicBezier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CubicBezier.swift; path = Pod/Classes/Math/CubicBezier.swift; sourceTree = ""; }; - 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Crashlytics.xcconfig; sourceTree = ""; }; - 8CA7CEF2E4E333C866B0744A716DBC48 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = iOS/Fabric.framework; sourceTree = ""; }; - 8CC6C53D14EE42A9C007047A01C4DF1F /* GAITrackedViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAITrackedViewController.h; path = Sources/GAITrackedViewController.h; sourceTree = ""; }; - 8E55C6090DEF8FF17C4877AB940FD591 /* DefaultBehaviors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultBehaviors.swift; path = Pod/Classes/Lifecycle/Framework/DefaultBehaviors.swift; sourceTree = ""; }; - 8F4D0D3C0C97E223CF4BAEE6393105E9 /* Pods_Services.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Services.framework; path = "Pods-Services.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 90AC5B33AAA6EF1AB9164725FFA0B6C3 /* Ligatures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Ligatures.swift; path = Sources/Ligatures.swift; sourceTree = ""; }; - 9270993480FEDFD0F12D1749E45B20D3 /* Compatability.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatability.swift; path = Source/Compatability.swift; sourceTree = ""; }; - 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Fabric.xcconfig; sourceTree = ""; }; - 957FC6AC38169C7173562AA6E6597C5A /* Alamofire-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alamofire-dummy.m"; sourceTree = ""; }; - 96822B1CA2B1F1B51992E9BAD9A99F96 /* Anchorage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Anchorage.framework; path = Anchorage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 96B35764F050EDE7B00132EF81A34F42 /* FloatingPoint+Scale.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "FloatingPoint+Scale.swift"; path = "Pod/Classes/Math/FloatingPoint+Scale.swift"; sourceTree = ""; }; - 96E262BA9A1492BA3FDC9E0786CF277A /* BonMot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = BonMot.framework; path = BonMot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 97594C320B5EFC4497444BB58291142A /* Shapes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Shapes.swift; path = Pod/Classes/Shapes/Shapes.swift; sourceTree = ""; }; - 9A1965AF062F89C7BDA3AE35620B5182 /* SimulatorStatusMagic-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SimulatorStatusMagic-dummy.m"; sourceTree = ""; }; - 9AB95055F14CE265D5FB56048A2E19D1 /* Pods-Services-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Services-dummy.m"; sourceTree = ""; }; - 9AEAE841E281C0D30AD94EEF9FC181AE /* Swiftilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Swiftilities.framework; path = Swiftilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9CA678F606DD3E9ABC1DBDF7400C03B2 /* Compatibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatibility.swift; path = Sources/Compatibility.swift; sourceTree = ""; }; + 0055556FD5940D94B5719D2CE306ED83 /* BonMot-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BonMot-dummy.m"; sourceTree = ""; }; + 00D5703DE6D32E8BEE77AC1C2A64D12F /* OHHTTPStubsSwift.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OHHTTPStubsSwift.swift; path = OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift; sourceTree = ""; }; + 0124BA8F81579A732104EE20E5A04876 /* AppCenterDistribute.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenterDistribute.framework; path = "AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework"; sourceTree = ""; }; + 01502087710687B101E4DBC35B149B69 /* NavTitleTransitionBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NavTitleTransitionBehavior.swift; path = "Pod/Classes/Lifecycle/Behaviors/Nav-Bar-Title-Transition/NavTitleTransitionBehavior.swift"; sourceTree = ""; }; + 016ABA6E4EC051693A5A08A27FAAA7DC /* Swiftilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Swiftilities-dummy.m"; sourceTree = ""; }; + 0172526E6D3CEFD172AD72474B7F1B03 /* pt.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pt.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj"; sourceTree = ""; }; + 01CDC0351ED7CEC107FB8A77489F99CE /* Alamofire-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alamofire-dummy.m"; sourceTree = ""; }; + 01FC0E2DFCCF55217572DC39EA5C6163 /* GPBMessage_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBMessage_PackagePrivate.h; path = objectivec/GPBMessage_PackagePrivate.h; sourceTree = ""; }; + 0245E1DD96C5A71E0976E257585FB875 /* FIRAppAssociationRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAppAssociationRegistration.m; path = Firebase/Core/FIRAppAssociationRegistration.m; sourceTree = ""; }; + 029DC932573FD3CFF2AB08725C770343 /* Pods_Services.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Services.framework; path = "Pods-Services.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 031FC7BA2605BE0368D9692DBDC15D81 /* Anchorage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Anchorage-umbrella.h"; sourceTree = ""; }; + 046CA33B599DC985AC83516113232E99 /* FIRInstanceIDAPNSInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAPNSInfo.h; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.h; sourceTree = ""; }; + 047E636E2BACE2765A28ADD8F0A0E5CA /* SDStatusBarOverriderPost9_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost9_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost9_0.m; sourceTree = ""; }; + 053874D026363AC0A03A09A01558AD61 /* GPBWireFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBWireFormat.h; path = objectivec/GPBWireFormat.h; sourceTree = ""; }; + 05E39D129D919E418F8D526AC9591021 /* Type.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = objectivec/google/protobuf/Type.pbobjc.h; sourceTree = ""; }; + 0613D7FC4E5B1B63B0C08F9883F7B6CB /* Timeline.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Timeline.swift; path = Source/Timeline.swift; sourceTree = ""; }; + 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.xcconfig; sourceTree = ""; }; + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = nanopb.framework; path = nanopb.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 075A60A7C92F557056B739FD7E6BD32C /* AccessibilityHelpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityHelpers.swift; path = Pod/Classes/AccessibilityHelpers/AccessibilityHelpers.swift; sourceTree = ""; }; + 08DA9B3BA661AA7124AE37AFA1396048 /* FIRInstanceIDTokenOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.m; sourceTree = ""; }; + 0904254547F200171C92FAE60BF75E4B /* FIRInstanceIDCheckinStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinStore.m; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.m; sourceTree = ""; }; + 0951EED81BCFA0803E2B141DE332E11D /* FIRMessagingConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingConnection.h; path = Firebase/Messaging/FIRMessagingConnection.h; sourceTree = ""; }; + 0AD7A8A7135C2FC81974892005E66656 /* Response.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Response.swift; path = Source/Response.swift; sourceTree = ""; }; + 0B179EF2E474E501FD5650C4ADF83782 /* GPBMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBMessage.h; path = objectivec/GPBMessage.h; sourceTree = ""; }; + 0B7FB0654F18D64FE0D7A2EAAC682B23 /* UIView+Instabug.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+Instabug.h"; path = "Instabug.framework/Headers/UIView+Instabug.h"; sourceTree = ""; }; + 0B8FDDE48F44189CC0D2FC2CAA0D5C49 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = iOS/Crashlytics.framework; sourceTree = ""; }; + 0D5C9E49FD0B96CC5F0A774F637668F2 /* FirebaseInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstanceID.h; path = Firebase/InstanceID/Public/FirebaseInstanceID.h; sourceTree = ""; }; + 0D70F6C27F2262A020CDFA6DBA6E0A95 /* ViewControllerLifecycleBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ViewControllerLifecycleBehavior.swift; path = Pod/Classes/Lifecycle/Framework/ViewControllerLifecycleBehavior.swift; sourceTree = ""; }; + 0D7113D1B1F68315334A5D6E5C78151A /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDictionary_PackagePrivate.h; path = objectivec/GPBDictionary_PackagePrivate.h; sourceTree = ""; }; + 0D8C01D7DC37A7E86CB6EB912842D669 /* GULLoggerCodes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerCodes.h; path = GoogleUtilities/Common/GULLoggerCodes.h; sourceTree = ""; }; + 0E1E27256DFC0F8898600F8DA01A1D3E /* FIRInstanceIDURLQueryItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDURLQueryItem.h; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.h; sourceTree = ""; }; + 0ED0360339FFD929C312164430AECEF5 /* Protocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Protocols.swift; path = Pod/Classes/Views/Textview/Protocols.swift; sourceTree = ""; }; + 0F5EF93A5BE453909C31B9C6554C95CD /* ja.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ja.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj"; sourceTree = ""; }; + 0FF31F44B7641D6494DCF4BD9B15D1D2 /* Instabug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Instabug.framework; sourceTree = ""; }; + 1064EA2176F4289B3F2DC02849A83825 /* GPBCodedOutputStream_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedOutputStream_PackagePrivate.h; path = objectivec/GPBCodedOutputStream_PackagePrivate.h; sourceTree = ""; }; + 106E91C219A27E966E2F6168D1D7F3CA /* FIRConfigurationInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfigurationInternal.h; path = Firebase/Core/Private/FIRConfigurationInternal.h; sourceTree = ""; }; + 10D13A0F900275F0E08660D22CBD3BD7 /* FIRInstanceID+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceID+Private.h"; path = "Firebase/InstanceID/FIRInstanceID+Private.h"; sourceTree = ""; }; + 11AF731E4071DCD5E34B4CA294302B92 /* AppCenterDistributeResources.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = AppCenterDistributeResources.bundle; path = "AppCenter-AppCenterDistributeResources.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + 11EF24F4E2A79E63296F2034D972DD0A /* FIRInstanceIDConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDConstants.h; path = Firebase/InstanceID/FIRInstanceIDConstants.h; sourceTree = ""; }; + 1248BFF6EDD2B0B1963D8E18335E0DCD /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Source/SessionDelegate.swift; sourceTree = ""; }; + 12D36157D372B866FB49CE4288D881E3 /* GtalkCore.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GtalkCore.pbobjc.h; path = Firebase/Messaging/Protos/GtalkCore.pbobjc.h; sourceTree = ""; }; + 1358F7B95EC32C0D0017CE9DBF481067 /* Pods-Services.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.develop.xcconfig"; sourceTree = ""; }; + 137550D164A3DC3110CE137D5BC383BE /* FIRApp.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRApp.m; path = Firebase/Core/FIRApp.m; sourceTree = ""; }; + 13811593551EEF5606EAEAC864156243 /* FIRInstanceIDKeyPairStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeyPairStore.m; path = Firebase/InstanceID/FIRInstanceIDKeyPairStore.m; sourceTree = ""; }; + 13EF5B0944ABC90005395BF63E59D1B9 /* SDStatusBarOverriderPost9_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost9_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost9_0.h; sourceTree = ""; }; + 13FC2F155F0438B5C95978061F39743F /* Anchorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Anchorage.swift; path = Source/Anchorage.swift; sourceTree = ""; }; + 14E3AE25C553C268ECABA7BA60383152 /* GULReachabilityChecker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityChecker.h; path = GoogleUtilities/Reachability/Private/GULReachabilityChecker.h; sourceTree = ""; }; + 1500A31AAD61B6B55D1541CEC1F8B821 /* FIRMessagingLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingLogger.m; path = Firebase/Messaging/FIRMessagingLogger.m; sourceTree = ""; }; + 1546A7379CB47F23D0B23E42B46F302D /* Swiftilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Swiftilities.modulemap; sourceTree = ""; }; + 15A36FCCB6649BA511408B3F1D946285 /* BonMot-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BonMot-Info.plist"; sourceTree = ""; }; + 15D1AB7F35E8D9D69E2A3E30D0AFA1F1 /* GULLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLogger.h; path = GoogleUtilities/Logger/Private/GULLogger.h; sourceTree = ""; }; + 1683A78B7B9007625AE95AAE42A96663 /* ko.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ko.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj"; sourceTree = ""; }; + 168D0C5421335ACFB5EBB53C584D8B5D /* GPBDescriptor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDescriptor.h; path = objectivec/GPBDescriptor.h; sourceTree = ""; }; + 16C9E7ABD2EF227BB7684A8307667F72 /* Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; sourceTree = ""; }; + 179351A254DB884FEB79BA11A69753BF /* IBGTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGTypes.h; path = Instabug.framework/Headers/IBGTypes.h; sourceTree = ""; }; + 17E33041B314FA837A3CAEB9DF3CDE9F /* OHHTTPStubs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = OHHTTPStubs.framework; path = OHHTTPStubs.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 180977BDD0E3E3ED4CC91DF5BCD29868 /* SDStatusBarOverriderPost8_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost8_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost8_3.m; sourceTree = ""; }; + 186880608DAD6477417FCC20081E68DF /* FIRInstanceIDCheckinPreferences+Internal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceIDCheckinPreferences+Internal.m"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m"; sourceTree = ""; }; + 18DE3A66023F031C118C9FA1671ACC93 /* FIRInstanceID+Private.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceID+Private.m"; path = "Firebase/InstanceID/FIRInstanceID+Private.m"; sourceTree = ""; }; + 1987EE9FAD1DBEC74F2716EA5DC6B2D0 /* Pods-Services.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.appstore.xcconfig"; sourceTree = ""; }; + 1997495D70A0AFDD3D4437EFFABE3048 /* SDStatusBarOverriderPost10_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost10_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost10_3.h; sourceTree = ""; }; + 1A2C2A90AABD3780C5969C4B208AF34F /* FIRAnalyticsConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsConfiguration.h; path = Firebase/Core/Private/FIRAnalyticsConfiguration.h; sourceTree = ""; }; + 1B6C4D3F28F3CBA7CF305CB592F85E32 /* IBGCrashReporting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGCrashReporting.h; path = Instabug.framework/Headers/IBGCrashReporting.h; sourceTree = ""; }; + 1B77C6FBEB46883FCDBBBF0333AAA959 /* LicenseFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LicenseFormatter.swift; path = Pod/Classes/LicenseFormatter/LicenseFormatter.swift; sourceTree = ""; }; + 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Instabug.xcconfig; sourceTree = ""; }; + 1C37EAC158A77C4D6904556D7810ED89 /* FIRInstanceIDKeyPair.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeyPair.h; path = Firebase/InstanceID/FIRInstanceIDKeyPair.h; sourceTree = ""; }; + 1D68553FA13FBC980DEA48AD8F4FF33C /* Protobuf-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Protobuf-Info.plist"; sourceTree = ""; }; + 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SimulatorStatusMagic.xcconfig; sourceTree = ""; }; + 1E28DADD6AFEF6A2BABCAA95C90585AE /* FIRInstanceIDCheckinPreferences_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences_Private.h; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h; sourceTree = ""; }; + 1F13E67C41FD3508A00AC0A6F6CA8A43 /* FIRMessagingRmq2PersistentStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRmq2PersistentStore.m; path = Firebase/Messaging/FIRMessagingRmq2PersistentStore.m; sourceTree = ""; }; + 1F16A3F715737A448BD6736FC7CE8C23 /* FirebaseMessaging-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseMessaging-dummy.m"; sourceTree = ""; }; + 1F6EBA7C6997FF0B01735341A694592F /* Type.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = objectivec/google/protobuf/Type.pbobjc.m; sourceTree = ""; }; + 1F937168226D3E9CD0FDFCA1B32629DA /* SDStatusBarOverriderPre8_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPre8_3.h; path = SDStatusBarManager/SDStatusBarOverriderPre8_3.h; sourceTree = ""; }; + 1FC6D095DAD42D44CCD8E75BCB2FE43F /* Pods-Services-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Services-acknowledgements.plist"; sourceTree = ""; }; + 20D53BC1D9D046786E39FFC97B7B43A7 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBWellKnownTypes.h; path = objectivec/GPBWellKnownTypes.h; sourceTree = ""; }; + 21518DB69A5249884D47AA1C030D65A1 /* GtalkCore.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GtalkCore.pbobjc.m; path = Firebase/Messaging/Protos/GtalkCore.pbobjc.m; sourceTree = ""; }; + 21921F807B4B34CE95F4333954EF9330 /* SDStatusBarOverriderPost10_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost10_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost10_3.m; sourceTree = ""; }; + 2207F5B391C14F1738C82A01AFB21DD1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 22D1FCC1043B4DD3CEA939877906ECD8 /* Any.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = objectivec/google/protobuf/Any.pbobjc.h; sourceTree = ""; }; + 22D8C3460BFD762A935246A9445DDDB6 /* nanopb-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-umbrella.h"; sourceTree = ""; }; + 233D6E7BF9D19F75FCD75EB9691646DB /* GoogleUtilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-prefix.pch"; sourceTree = ""; }; + 23F5E88F86F777E70C48C646149BA42B /* Transform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transform.swift; path = Sources/Transform.swift; sourceTree = ""; }; + 245165C00B0AB8EFA8DF3D2BBC1F3C8D /* TableSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableSection.swift; path = Pod/Classes/TableViewHelpers/TableSection.swift; sourceTree = ""; }; + 247C04FA03FB22629ED9C337A195F8F6 /* OHHTTPStubsResponse+JSON.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "OHHTTPStubsResponse+JSON.h"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h"; sourceTree = ""; }; + 24FEA1649F859C025807618A170C83B1 /* FIRInstanceIDStringEncoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStringEncoding.h; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.h; sourceTree = ""; }; + 258251CAB54F309E8E640653850C4B32 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBWellKnownTypes.m; path = objectivec/GPBWellKnownTypes.m; sourceTree = ""; }; + 26820BF7BDA3D0A1D104CE81E2CF5EEE /* Notifications.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Notifications.swift; path = Source/Notifications.swift; sourceTree = ""; }; + 26880FF9FEB2270469CDC3F44CFC51BE /* FIRInstanceIDCombinedHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCombinedHandler.m; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.m; sourceTree = ""; }; + 2707310D83A1EE6275AED80C0CF694FE /* ContextualAlternates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContextualAlternates.swift; path = Sources/ContextualAlternates.swift; sourceTree = ""; }; + 2765A7D6EF27B9AB42D6279A14D1669A /* UITextView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITextView+Extensions.swift"; path = "Pod/Classes/Views/Textview/UITextView+Extensions.swift"; sourceTree = ""; }; + 288D811BFAFF4D05B72871868528971C /* NamedStyles.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NamedStyles.swift; path = Sources/NamedStyles.swift; sourceTree = ""; }; + 29977CBD0F0F1352A376A22E58D14F56 /* FIRMessagingInternalUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingInternalUtilities.h; path = Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h; sourceTree = ""; }; + 2B6941F28C59EA39D79CAAF8560210A4 /* Pods-Services-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Services-acknowledgements.markdown"; sourceTree = ""; }; + 2B76802A61020D8F2FF87DBC22F95501 /* FIRInstanceIDAuthService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthService.h; path = Firebase/InstanceID/FIRInstanceIDAuthService.h; sourceTree = ""; }; + 2C51C1D95A23094AED0ABE47DE23F077 /* FIRMessagingClient.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingClient.h; path = Firebase/Messaging/FIRMessagingClient.h; sourceTree = ""; }; + 2CA2C241BE9B8942C2622A8288159183 /* Internal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Internal.swift; path = Source/Internal.swift; sourceTree = ""; }; + 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.xcconfig; sourceTree = ""; }; + 2D45D29B213853B66B8B282991CCF083 /* GULLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerLevel.h; path = GoogleUtilities/Logger/Public/GULLoggerLevel.h; sourceTree = ""; }; + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstanceID.framework; path = FirebaseInstanceID.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DA62A31E606D66A0A8DF99FFB00CB54 /* ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; sourceTree = ""; }; + 2DE296C57E7600238C8BE1E7BEE31B00 /* Pods-PRODUCTNAME-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-acknowledgements.plist"; sourceTree = ""; }; + 2DF285A229D15CB8F3DFBB3DD3DC7884 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownField_PackagePrivate.h; path = objectivec/GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; + 2E5D20BCCFC283EBF43CD654944F92FB /* Any.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = objectivec/google/protobuf/Any.pbobjc.m; sourceTree = ""; }; + 2F6E205211513A677E520BAD5BD8C183 /* AnchorGroupProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnchorGroupProvider.swift; path = Source/AnchorGroupProvider.swift; sourceTree = ""; }; + 2F6F1BBF9B142B5EF49F87D2D044E829 /* OHHTTPStubs-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-umbrella.h"; sourceTree = ""; }; + 2F85F03D3204EDFA79866F18C991616C /* FormattedTextField.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FormattedTextField.swift; path = Pod/Classes/FormattedTextField/FormattedTextField.swift; sourceTree = ""; }; + 2FA78D05699B3A7B758DCA452BE2C72E /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/MessageUI.framework; sourceTree = DEVELOPER_DIR; }; + 2FDE57075083813209769DB1ECBA097C /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = objectivec/google/protobuf/Timestamp.pbobjc.h; sourceTree = ""; }; + 300E24828164112EB400CCFD1E0D55B9 /* Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig"; sourceTree = ""; }; + 30C8877C44A2A9CEF55FFA4B756AB34A /* FIRInstanceIDDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDDefines.h; path = Firebase/InstanceID/FIRInstanceIDDefines.h; sourceTree = ""; }; + 318F5854818D012A621F4EE3E8A310B3 /* FIRMessagingClient.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingClient.m; path = Firebase/Messaging/FIRMessagingClient.m; sourceTree = ""; }; + 319AFABD7CD5670EEEE2D2BA15A360BD /* GULLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULLogger.m; path = GoogleUtilities/Logger/GULLogger.m; sourceTree = ""; }; + 31ADA9CE18EE4DD7B2A1D3B81C8C8B97 /* Crashlytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Crashlytics.h; path = iOS/Crashlytics.framework/Headers/Crashlytics.h; sourceTree = ""; }; + 322AE82498430F3AA39C51C2BC4FB15F /* SDStatusBarOverriderPost12_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost12_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost12_0.h; sourceTree = ""; }; + 322D077B4897B4E6A8C083170A121575 /* pb_decode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_decode.h; sourceTree = ""; }; + 32FC646A39309A016A43413CF59D0AB3 /* Pods-PRODUCTNAME-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-Info.plist"; sourceTree = ""; }; + 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.xcconfig; sourceTree = ""; }; + 33A4868B2CB72C28A43C9793FA150418 /* BonMot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = BonMot.framework; path = BonMot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 346C27A97925A47261C4B6AC76983CD3 /* Swiftilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Swiftilities-Info.plist"; sourceTree = ""; }; + 356BEB97A3924CA7A9EFA6E39B529298 /* FIRMessagingPersistentSyncMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPersistentSyncMessage.m; path = Firebase/Messaging/FIRMessagingPersistentSyncMessage.m; sourceTree = ""; }; + 35BA4A04ECE9B5B06B1021FB70BBB8E9 /* Alamofire-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Alamofire-Info.plist"; sourceTree = ""; }; + 35D0212C3DBD3EB9B48F92FE6E705124 /* GULNetworkMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkMessageCode.h; path = GoogleUtilities/Network/Private/GULNetworkMessageCode.h; sourceTree = ""; }; + 360D12ED7F2D4981DBE39DE4FCDC76A3 /* FIRMessagingConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingConstants.h; path = Firebase/Messaging/FIRMessagingConstants.h; sourceTree = ""; }; + 365D0C4EEEA6C8DB030220CF3E73772A /* UIView+KeyboardLayoutGuide.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+KeyboardLayoutGuide.swift"; path = "Pod/Classes/Keyboard/UIView+KeyboardLayoutGuide.swift"; sourceTree = ""; }; + 36624989E8CA8F0B22557AD8E3ACAEEF /* GULUserDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULUserDefaults.m; path = GoogleUtilities/UserDefaults/GULUserDefaults.m; sourceTree = ""; }; + 367EF090BA9D626CCBE6C72374BAB47B /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoding.swift; path = Source/ParameterEncoding.swift; sourceTree = ""; }; + 367F00084F5782810F06E3AE60988239 /* FIRBundleUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRBundleUtil.m; path = Firebase/Core/FIRBundleUtil.m; sourceTree = ""; }; + 3739B5667A1C1B8452C08E5FB55014E5 /* FIRInstanceIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenStore.m; path = Firebase/InstanceID/FIRInstanceIDTokenStore.m; sourceTree = ""; }; + 37D1089A0FB89C55B768CC26C804A7B2 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionRegistry.m; path = objectivec/GPBExtensionRegistry.m; sourceTree = ""; }; + 37E010E6C2F14B116AD0A6E40D547F39 /* FIRMessagingSecureSocket.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingSecureSocket.h; path = Firebase/Messaging/FIRMessagingSecureSocket.h; sourceTree = ""; }; + 38337959621A4D9065BD17ACB25371AD /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = objectivec/google/protobuf/Wrappers.pbobjc.m; sourceTree = ""; }; + 39011BD939C3832DBBFC0228D3EF5804 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown"; sourceTree = ""; }; + 399A0F9FCF8F163E53341ADFC13A530F /* GPBDescriptor_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDescriptor_PackagePrivate.h; path = objectivec/GPBDescriptor_PackagePrivate.h; sourceTree = ""; }; + 3B333D83F4602F037A199CE1061A7A79 /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = objectivec/google/protobuf/FieldMask.pbobjc.h; sourceTree = ""; }; + 3B5E83DF94AA1871CCE123E6D44F0B70 /* GULMutableDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULMutableDictionary.m; path = GoogleUtilities/Network/GULMutableDictionary.m; sourceTree = ""; }; + 3BA9EA5998AA76F74EE798C3CBBECA9D /* FIRMessagingPacketQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPacketQueue.m; path = Firebase/Messaging/FIRMessagingPacketQueue.m; sourceTree = ""; }; + 3C1809F979F3942E4C48A86D0F20B10B /* FIRMessagingVersionUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingVersionUtilities.m; path = Firebase/Messaging/FIRMessagingVersionUtilities.m; sourceTree = ""; }; + 3C43A20C9129EB73F5BA4F3C40D9A27A /* Pods_PRODUCTNAME.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PRODUCTNAME.framework; path = "Pods-PRODUCTNAME.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C9D78BDFE3971F2EF43F1EE93290481 /* OHHTTPStubsResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsResponse.m; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.m; sourceTree = ""; }; + 3CE8A623704EA768F5F5576533B75CC4 /* Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig"; sourceTree = ""; }; + 3CFCAB771CD0ED282F14A09984871047 /* MultipartFormData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartFormData.swift; path = Source/MultipartFormData.swift; sourceTree = ""; }; + 3D6419DC93CAC1E865DD9A730B5C8623 /* AcknowledgementsListViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementsListViewModel.swift; path = Pod/Classes/Acknowledgements/AcknowledgementsListViewModel.swift; sourceTree = ""; }; + 3D6B1D921CE2EF324C684690E9B44CD4 /* AFError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AFError.swift; path = Source/AFError.swift; sourceTree = ""; }; + 3D735903962EFF3FC6A7517312F923CA /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = Firebase/Core/Private/FIRDependency.h; sourceTree = ""; }; + 3E381DBDE829EC743F4F0A730A0EA4E5 /* GULNetworkConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkConstants.m; path = GoogleUtilities/Network/GULNetworkConstants.m; sourceTree = ""; }; + 3F5BB4D560F726BDE1F35DA184B1268B /* TintedButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TintedButton.swift; path = Pod/Classes/TintedButton/TintedButton.swift; sourceTree = ""; }; + 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalyticsInterop.xcconfig; sourceTree = ""; }; + 422359491E6C68A5FEFC4E916C0385EF /* Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; sourceTree = ""; }; + 422661E817D097522D8B376CDBD2FD9C /* SimulatorStatusMagic-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SimulatorStatusMagic-umbrella.h"; sourceTree = ""; }; + 433FD3F0C39CB9CDDF7F51F624242518 /* SDStatusBarOverriderPre8_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPre8_3.m; path = SDStatusBarManager/SDStatusBarOverriderPre8_3.m; sourceTree = ""; }; + 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 43F95FB28B3B3DDC58B3E70C591BD759 /* Pods-Services-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Services-umbrella.h"; sourceTree = ""; }; + 44001909662AEC3C8F8AB4E8044AB034 /* FIRInstanceIDCheckinService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinService.m; path = Firebase/InstanceID/FIRInstanceIDCheckinService.m; sourceTree = ""; }; + 441C8E5411061099355CF78039DCB16A /* NavBarHairlineFadeBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NavBarHairlineFadeBehavior.swift; path = "Pod/Classes/Lifecycle/Behaviors/Nav-Bar-Hairline-Fade/NavBarHairlineFadeBehavior.swift"; sourceTree = ""; }; + 444803A0ADD399B49C628CFC2947F5D0 /* KeychainAccess-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "KeychainAccess-Info.plist"; sourceTree = ""; }; + 44A66697CB999F1B94BE112FF3F6082E /* FIRMessagingCheckinService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingCheckinService.m; path = Firebase/Messaging/FIRMessagingCheckinService.m; sourceTree = ""; }; + 44CE758ABDDC428058091BE3EF7C9451 /* GoogleUtilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleUtilities-dummy.m"; sourceTree = ""; }; + 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = OHHTTPStubs.xcconfig; sourceTree = ""; }; + 45BCED46E7DDF7FBA46DB0CC8B1E58EB /* FIRInstanceIDURLQueryItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDURLQueryItem.m; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.m; sourceTree = ""; }; + 45D7EE49F14DA03DC27AA4631DE48483 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Source/Result.swift; sourceTree = ""; }; + 45FA4D2E7421B8D456A7B6F36884B54B /* GoogleAppMeasurement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GoogleAppMeasurement.framework; path = Frameworks/GoogleAppMeasurement.framework; sourceTree = ""; }; + 466630EDA0868AA0AB1CEBACE48F76AB /* FIRInstanceIDBackupExcludedPlist.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDBackupExcludedPlist.m; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m; sourceTree = ""; }; + 468332F23F5D358DB2288F3934AEC350 /* FIRMessagingDelayedMessageQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingDelayedMessageQueue.m; path = Firebase/Messaging/FIRMessagingDelayedMessageQueue.m; sourceTree = ""; }; + 4707DEF6F61CF955E8D0164566D43983 /* FIRMessagingVersionUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingVersionUtilities.h; path = Firebase/Messaging/FIRMessagingVersionUtilities.h; sourceTree = ""; }; + 47EBEF062D1954D670444D5FB49CB050 /* GULSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSwizzler.h; path = GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h; sourceTree = ""; }; + 488D7FCF0C4C3011E9931E973C97CB62 /* IBGNetworkLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGNetworkLogger.h; path = Instabug.framework/Headers/IBGNetworkLogger.h; sourceTree = ""; }; + 4A12FC33DD08260C9C378A9C2A227833 /* GPBArray.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBArray.h; path = objectivec/GPBArray.h; sourceTree = ""; }; + 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Anchorage.xcconfig; sourceTree = ""; }; + 4B0940BB70F444E65F6DB52323B97369 /* FIRInstanceIDVersionUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDVersionUtilities.h; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.h; sourceTree = ""; }; + 4B1D3820BB2870B22224C025F97B495A /* GPBDescriptor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBDescriptor.m; path = objectivec/GPBDescriptor.m; sourceTree = ""; }; + 4B4AA562F866C56D8D686538218F79EA /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = Firebase/Core/Private/FIRLibrary.h; sourceTree = ""; }; + 4C3439A40A51D1DD58761BACB9331DD2 /* Pods-PRODUCTNAME.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.develop.xcconfig"; sourceTree = ""; }; + 4D0B98AEB62ED9CED697D20516060929 /* GoogleUtilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleUtilities-Info.plist"; sourceTree = ""; }; + 4D827CD1FACB9020945F3B62976196F5 /* GPBCodedInputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedInputStream.h; path = objectivec/GPBCodedInputStream.h; sourceTree = ""; }; + 4DE6952B80D386C75EA01A7B003A923F /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = objectivec/google/protobuf/Wrappers.pbobjc.h; sourceTree = ""; }; + 4E3D53C87F3183ECB9828E9F2CC13CEF /* AttributedStringTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AttributedStringTransformation.swift; path = Sources/UIKit/AttributedStringTransformation.swift; sourceTree = ""; }; + 4E4A10F6099BBA9290EDF1F50E4E1E06 /* FIRComponentContainerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainerInternal.h; path = Firebase/Core/Private/FIRComponentContainerInternal.h; sourceTree = ""; }; + 4EC0877FA9D2F6B5649644D06256D79A /* Anchorage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Anchorage-prefix.pch"; sourceTree = ""; }; + 4F7DFC7F79DE29AD380D6C23EF374F66 /* TailoredSwiftTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TailoredSwiftTextView.swift; path = Pod/Classes/Views/Textview/TailoredSwiftTextView.swift; sourceTree = ""; }; + 4FC123B26387B1A38B1AAB531554C64E /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = Firebase/Core/Private/FIROptionsInternal.h; sourceTree = ""; }; + 4FC53E880281E6082EF5E821D70B924D /* IBGSurveys.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGSurveys.h; path = Instabug.framework/Headers/IBGSurveys.h; sourceTree = ""; }; + 4FCB1518EBBFFD314F997C63F2AE720F /* Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Compatibility.h; path = OHHTTPStubs/Sources/Compatibility.h; sourceTree = ""; }; + 5079F288993DCE2E3F57BD1ECD985F0E /* BonMot-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BonMot-prefix.pch"; sourceTree = ""; }; + 5099DC3344B97A39551F2FD82C61B62E /* FirebaseMessaging-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseMessaging-Info.plist"; sourceTree = ""; }; + 5112CE97A821E9C641D75D1ADAC3EB32 /* TextAlignmentConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextAlignmentConstraint.swift; path = Sources/UIKit/TextAlignmentConstraint.swift; sourceTree = ""; }; + 511A6AAEF7B2FA3135202FCC07BF3E65 /* FIRAnalyticsInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsInterop.h; path = Interop/Analytics/Public/FIRAnalyticsInterop.h; sourceTree = ""; }; + 518BACD57DCD1AA45BE9270B8C5CF1B5 /* Pods-PRODUCTNAME.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.sprint.xcconfig"; sourceTree = ""; }; + 5215C876BC30D194764B41B21031B21F /* FIRInstanceIDCheckinService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinService.h; path = Firebase/InstanceID/FIRInstanceIDCheckinService.h; sourceTree = ""; }; + 526F1F36C6164054C3753D3E4D5C5C6B /* Clamping.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Clamping.swift; path = Pod/Classes/Math/Clamping.swift; sourceTree = ""; }; + 52C88D2EB51952A1D85A0AB4AD8FE1D6 /* Compatibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatibility.swift; path = Sources/Compatibility.swift; sourceTree = ""; }; + 536F55571CB5D4E8C4CD313EFFC98897 /* GPBCodedInputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBCodedInputStream.m; path = objectivec/GPBCodedInputStream.m; sourceTree = ""; }; + 53F88E4F0E3A11E9B5D721DEEDEB2F09 /* SDStatusBarOverriderPost8_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost8_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost8_3.h; sourceTree = ""; }; + 5439C399E40C811A0CC58CD80BF419DB /* GULAppEnvironmentUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppEnvironmentUtil.h; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h; sourceTree = ""; }; + 547CDF4449B3AF5D1990F54FD639448E /* UIKit+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIKit+Helpers.swift"; path = "Sources/UIKit/UIKit+Helpers.swift"; sourceTree = ""; }; + 548F85D6FB2D9B296B3CB2FD0B313CDC /* TaskDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskDelegate.swift; path = Source/TaskDelegate.swift; sourceTree = ""; }; + 552F3B93D76BA12F543F0275D11FB3F6 /* UITableView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITableView+Extensions.swift"; path = "Pod/Classes/TableViewHelpers/UITableView+Extensions.swift"; sourceTree = ""; }; + 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AppCenter.xcconfig; sourceTree = ""; }; + 55C1593407CAC28F4349FBA65B0C1BD9 /* FIRInstanceIDTokenInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenInfo.m; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.m; sourceTree = ""; }; + 55D73A9343E88A26AE65A4223D8C07DF /* Alamofire-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-umbrella.h"; sourceTree = ""; }; + 5674AE212A0219BB0B7D3C5798B9D7E6 /* Answers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Answers.h; path = iOS/Crashlytics.framework/Headers/Answers.h; sourceTree = ""; }; + 569222352AED8AA275E1295F319C179D /* Anchorage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Anchorage-dummy.m"; sourceTree = ""; }; + 56C526BDE19AC726B077CA91F4A3D248 /* FIRInstanceIDKeyPair.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeyPair.m; path = Firebase/InstanceID/FIRInstanceIDKeyPair.m; sourceTree = ""; }; + 571718858875E6D21B448DAAA8A43D00 /* FIRInstanceIDTokenOperation+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDTokenOperation+Private.h"; path = "Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h"; sourceTree = ""; }; + 5725B7F7891756CBC38A7C3FFBA0605D /* FIRMessagingRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRegistrar.h; path = Firebase/Messaging/FIRMessagingRegistrar.h; sourceTree = ""; }; + 5805433E9EE4075EBAE342A288525AD4 /* Duration.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = objectivec/google/protobuf/Duration.pbobjc.h; sourceTree = ""; }; + 58BC5AB95FAF621615835A4436B69D8C /* GPBUnknownField.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownField.h; path = objectivec/GPBUnknownField.h; sourceTree = ""; }; + 598E11382120CC7243651B55798ADF64 /* Pods-PRODUCTNAME-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PRODUCTNAME-frameworks.sh"; sourceTree = ""; }; + 59995D0C9E351E7C567DF118C940304B /* PlaceholderTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PlaceholderTextView.swift; path = Pod/Classes/Views/Textview/PlaceholderTextView.swift; sourceTree = ""; }; + 5A3F12E1757587C015AB1F285348CFAB /* OHHTTPStubsResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsResponse.h; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.h; sourceTree = ""; }; + 5AC714289EA97E67199CA997655EAF27 /* FIRInstanceIDTokenInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenInfo.h; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.h; sourceTree = ""; }; + 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.xcconfig; sourceTree = ""; }; + 5B654B4B042BA7DC93766943A643E42B /* FirebaseMessaging.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseMessaging.framework; path = FirebaseMessaging.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5BA55509BAF2F35EE0DDC61B513006A6 /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseCoreDiagnostics.framework; path = Frameworks/FirebaseCoreDiagnostics.framework; sourceTree = ""; }; + 5BD0138F17C5CEC5217CDE58354221B3 /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = objectivec/google/protobuf/SourceContext.pbobjc.h; sourceTree = ""; }; + 5BE4AF9D183DD4AA86ED02D801EC64FA /* nanopb-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "nanopb-Info.plist"; sourceTree = ""; }; + 5C494458D65556B106276B45877C5407 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = Firebase/Core/Private/FIRLogger.h; sourceTree = ""; }; + 5CF43C772DF570A45DC9831438386FF8 /* FIRComponentContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentContainer.m; path = Firebase/Core/FIRComponentContainer.m; sourceTree = ""; }; + 5D1F592A03F29834A482A527C26C43F1 /* LifecycleBehaviorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LifecycleBehaviorViewController.swift; path = Pod/Classes/Lifecycle/Framework/LifecycleBehaviorViewController.swift; sourceTree = ""; }; + 5D2F76C4975A9F75ECFED7459246BDCE /* NSLayoutAnchor+MultiplierConstraints.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutAnchor+MultiplierConstraints.swift"; path = "Source/NSLayoutAnchor+MultiplierConstraints.swift"; sourceTree = ""; }; + 5D6FB40F4F28DA6BC422DDDDBBC7CDA6 /* FirebaseMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseMessaging.h; path = Firebase/Messaging/FirebaseMessaging.h; sourceTree = ""; }; + 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Alamofire.framework; path = Alamofire.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D79D6EFCA519A3D859AD623DEEA3E97 /* Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alamofire.swift; path = Source/Alamofire.swift; sourceTree = ""; }; + 5D93E1401B7CC5204F8F2112E6F2DF1A /* Composable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Composable.swift; path = Sources/Composable.swift; sourceTree = ""; }; + 5EB40E5CF6D5BE4269E687E374531BA9 /* IBGChats.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGChats.h; path = Instabug.framework/Headers/IBGChats.h; sourceTree = ""; }; + 5F619742AF64CEB785C8717E281D3DA7 /* NSError+FIRMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+FIRMessaging.h"; path = "Firebase/Messaging/NSError+FIRMessaging.h"; sourceTree = ""; }; + 5F9E4B9D5FF21ED1F4AB75BA5BA13598 /* FIRMessagingPacketQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPacketQueue.h; path = Firebase/Messaging/FIRMessagingPacketQueue.h; sourceTree = ""; }; + 5FBA28A120B7A31F4D7E17E23F881916 /* FIRAnalyticsConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAnalyticsConfiguration.m; path = Firebase/Core/FIRAnalyticsConfiguration.m; sourceTree = ""; }; + 5FD4F06E7B97586342DC5F130C93CAD6 /* FIRInstanceIDTokenFetchOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenFetchOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h; sourceTree = ""; }; + 60057B688B56F5C62D15997BB9EDEFDD /* GULAppDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h; sourceTree = ""; }; + 6010A7276EC10495D966DCFE5E3C113E /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; }; + 6228C304CE54B8A03AEF3954707FB619 /* FeedbackPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FeedbackPresenter.swift; path = Pod/Classes/AboutView/FeedbackPresenter.swift; sourceTree = ""; }; + 623AE596A3622CB246F0C91BF962A5EA /* FIRMessagingTopicsCommon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingTopicsCommon.h; path = Firebase/Messaging/FIRMessagingTopicsCommon.h; sourceTree = ""; }; + 62F4647B8C0D1352B1C58A2CCAC8F8A1 /* ServerTrustPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServerTrustPolicy.swift; path = Source/ServerTrustPolicy.swift; sourceTree = ""; }; + 63202DA0FE6824272136B2EC50F9FB63 /* Pods-Services.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.debug.xcconfig"; sourceTree = ""; }; + 63782DD22D80D12F0478617EBF8A6E9E /* pb_common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_common.h; sourceTree = ""; }; + 6407CC37ECE767179AE4ED00301D5C52 /* GULOriginalIMPConvenienceMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULOriginalIMPConvenienceMacros.h; path = GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h; sourceTree = ""; }; + 65DFDCD7CA8EB72916D84A809A50C7FD /* SDStatusBarManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarManager.m; path = SDStatusBarManager/SDStatusBarManager.m; sourceTree = ""; }; + 6605561032963C6225A616C84441A72F /* IndexPath+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "IndexPath+Extensions.swift"; path = "Pod/Classes/TableViewHelpers/IndexPath+Extensions.swift"; sourceTree = ""; }; + 661D315940B1DDA7A83242BBBB7CFCA3 /* FIRInstanceIDTokenManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenManager.m; path = Firebase/InstanceID/FIRInstanceIDTokenManager.m; sourceTree = ""; }; + 662B607559C369907018526CD34E7A82 /* FIRMessagingPendingTopicsList.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPendingTopicsList.h; path = Firebase/Messaging/FIRMessagingPendingTopicsList.h; sourceTree = ""; }; + 670326828280195E95A7805733428555 /* GPBBootstrap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBBootstrap.h; path = objectivec/GPBBootstrap.h; sourceTree = ""; }; + 677C759A60BA1A68EC54588ED16024FD /* FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID.h; path = Firebase/InstanceID/Public/FIRInstanceID.h; sourceTree = ""; }; + 67D20FEE4726CCB26A931435C6F7F8D6 /* FIRMessagingSecureSocket.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingSecureSocket.m; path = Firebase/Messaging/FIRMessagingSecureSocket.m; sourceTree = ""; }; + 67E6336A4DE03D2B54BB4E2D5C377405 /* FIRMessagingConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingConstants.m; path = Firebase/Messaging/FIRMessagingConstants.m; sourceTree = ""; }; + 6B4A56D8EB5978D426BDC59DC1AA5E2C /* FIRMessagingContextManagerService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingContextManagerService.h; path = Firebase/Messaging/FIRMessagingContextManagerService.h; sourceTree = ""; }; + 6C651771BDA251122C0517F98DD229C4 /* FIRMessagingContextManagerService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingContextManagerService.m; path = Firebase/Messaging/FIRMessagingContextManagerService.m; sourceTree = ""; }; + 6CF234F15578D78CE0B9F963AE67AD0A /* CLSReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSReport.h; path = iOS/Crashlytics.framework/Headers/CLSReport.h; sourceTree = ""; }; + 6CFEFDB61382511167CBE5BFA016DFF7 /* FIRMessagingExtensionHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingExtensionHelper.m; path = Firebase/Messaging/FIRMessagingExtensionHelper.m; sourceTree = ""; }; + 6D0CAF61CDA366988A208A7B3648AB10 /* FIRMessagingTopicOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingTopicOperation.m; path = Firebase/Messaging/FIRMessagingTopicOperation.m; sourceTree = ""; }; + 6DF740D3ACE024C9F6487F0DBFBBC4B7 /* GULAppDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppDelegateSwizzler.m; path = GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m; sourceTree = ""; }; + 6E2CFBCCEE9CCE0907B805548198E2D4 /* StringStyle+Part.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "StringStyle+Part.swift"; path = "Sources/StringStyle+Part.swift"; sourceTree = ""; }; + 6EB8515E357A8EA23661EBCD579561C3 /* NSError+FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+FIRInstanceID.m"; path = "Firebase/InstanceID/NSError+FIRInstanceID.m"; sourceTree = ""; }; + 6EBEFE4F4DF5F7C86F8F3F2C30FC2380 /* SimulatorStatusMagic-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SimulatorStatusMagic-dummy.m"; sourceTree = ""; }; + 6F446B65463479D1A1BC7E615FB1DB21 /* AboutView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AboutView.swift; path = Pod/Classes/AboutView/AboutView.swift; sourceTree = ""; }; + 6F5FE5A0393B7EA11DA9DBF03DDF5479 /* FIRInstanceIDTokenOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.h; sourceTree = ""; }; + 6FF4D0CB4786B5D9882E4D069869A3CF /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBProtocolBuffers_RuntimeSupport.h; path = objectivec/GPBProtocolBuffers_RuntimeSupport.h; sourceTree = ""; }; + 71A5AB122315590AD0A59A0DA56F3DA9 /* IBGLog.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGLog.h; path = Instabug.framework/Headers/IBGLog.h; sourceTree = ""; }; + 71D265F83D526F8D4CBAF591F57A1C35 /* GULNetwork.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetwork.h; path = GoogleUtilities/Network/Private/GULNetwork.h; sourceTree = ""; }; + 7240263E6AB16234AD51BABC7BEDBFD0 /* FIRMessagingRemoteNotificationsProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRemoteNotificationsProxy.h; path = Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h; sourceTree = ""; }; + 72AA8EF20A9E0ED207B17A82A67948D7 /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = Firebase/Core/Private/FIRComponentContainer.h; sourceTree = ""; }; + 72C7D6029AC9F37ABD0F2A4F076D6125 /* FirebaseInstanceID-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstanceID-Info.plist"; sourceTree = ""; }; + 73047CD3A9D6F102084B6565479FD975 /* OHHTTPStubsResponse+JSON.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubsResponse+JSON.m"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.m"; sourceTree = ""; }; + 73B6B0B82C4B090FD5CCE3E4B3185607 /* GULReachabilityMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityMessageCode.h; path = GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h; sourceTree = ""; }; + 73D447A7F190F1E1C93B83CA52F803B4 /* Pods-Services-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Services-Info.plist"; sourceTree = ""; }; + 741B01C4F4159696D4237F6F4D3A98BB /* OHHTTPStubs-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-prefix.pch"; sourceTree = ""; }; + 74BE747D93A2FF0D9596DFEB89B88506 /* cs.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = cs.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj"; sourceTree = ""; }; + 7558233F38BB01572FA6F6C87087DE05 /* Keyboard.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Keyboard.swift; path = Pod/Classes/Keyboard/Keyboard.swift; sourceTree = ""; }; + 7579D1AD4020ED9620DFC5844850FF1E /* SimulatorStatusMagic-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SimulatorStatusMagic-prefix.pch"; sourceTree = ""; }; + 76848D31B6A54F9167B3E81B2B157273 /* SDStatusBarOverriderPost10_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost10_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost10_0.h; sourceTree = ""; }; + 772EBD4355380FAEEEE486F50277CA1F /* FIRVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVersion.m; path = Firebase/Core/FIRVersion.m; sourceTree = ""; }; + 773F43FA50FABF1CE0C562282F32D624 /* DispatchQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Alamofire.swift"; path = "Source/DispatchQueue+Alamofire.swift"; sourceTree = ""; }; + 7750A59221DB77FAF80CF7B06B985ABA /* FIRMessagingReceiver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingReceiver.m; path = Firebase/Messaging/FIRMessagingReceiver.m; sourceTree = ""; }; + 7798FFAA50C6E5C495F258D8A51AFCF9 /* FIRMessagingPubSub.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPubSub.h; path = Firebase/Messaging/FIRMessagingPubSub.h; sourceTree = ""; }; + 78082F41A23883083EE4061BFC18A4D3 /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = Firebase/Core/Private/FIRErrors.h; sourceTree = ""; }; + 780F31022D4CCCEEEF6B0433A8907F93 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBExtensionInternals.h; path = objectivec/GPBExtensionInternals.h; sourceTree = ""; }; + 781146DAC6F2B33CBAB88F5B7480DA3C /* FIRInstanceIDAuthService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthService.m; path = Firebase/InstanceID/FIRInstanceIDAuthService.m; sourceTree = ""; }; + 781DC562E9BB6624DE3FB5B273AEF265 /* Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh"; sourceTree = ""; }; + 78277DF682670FCB6D1E611B6DD72010 /* FIRInstanceIDTokenDeleteOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenDeleteOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h; sourceTree = ""; }; + 784571D4952D4EA67F2018794826B771 /* KeychainAccess.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = KeychainAccess.modulemap; sourceTree = ""; }; + 7852EA1E7C25798259AEA5BCE126639F /* Tracking+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Tracking+Adaptive.swift"; path = "Sources/UIKit/Tracking+Adaptive.swift"; sourceTree = ""; }; + 786594362231C88055784CE1F30F160D /* StringStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StringStyle.swift; path = Sources/StringStyle.swift; sourceTree = ""; }; + 789045C4CD88187B1C8B6952AD65877D /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBProtocolBuffers.h; path = objectivec/GPBProtocolBuffers.h; sourceTree = ""; }; + 7902953F39F914B13DAD07D6C494973D /* FIRLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRLogger.m; path = Firebase/Core/FIRLogger.m; sourceTree = ""; }; + 7930F6E4B1DBA1F8B3A51893DC47D6D9 /* FIRMessagingCheckinService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingCheckinService.h; path = Firebase/Messaging/FIRMessagingCheckinService.h; sourceTree = ""; }; + 793A451BCFED3B0D33EF91ABA0E76DC0 /* MutableCopying.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MutableCopying.swift; path = Sources/MutableCopying.swift; sourceTree = ""; }; + 79B0EA6DE3F64B8EB2ED292B450C2FBB /* Instabug.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Instabug.h; path = Instabug.framework/Headers/Instabug.h; sourceTree = ""; }; + 7A62C867EDE3F5810D57F99ED04E9BA0 /* Struct.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = objectivec/google/protobuf/Struct.pbobjc.h; sourceTree = ""; }; + 7A99BF2E906BA57B9D716EC2F28447CF /* Log.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Log.swift; path = Pod/Classes/Logging/Log.swift; sourceTree = ""; }; + 7B31944D9854B90AB402DAEBC2714BCB /* Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig"; sourceTree = ""; }; + 7BE9D1869AAADCD42062E01D5D3C87C8 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownFieldSet_PackagePrivate.h; path = objectivec/GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; + 7C5A26153063FDC9CF29CACEBFDCE19B /* GPBUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUtilities.h; path = objectivec/GPBUtilities.h; sourceTree = ""; }; + 7D3E35ACC5108C1B4DEF24DD53900541 /* Keychain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Keychain.swift; path = Lib/KeychainAccess/Keychain.swift; sourceTree = ""; }; + 7D5ABA89BFABB034F15503FA4EA2C665 /* Struct.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = objectivec/google/protobuf/Struct.pbobjc.m; sourceTree = ""; }; + 7DF32B5609DBC1BE477D33A94686964D /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBExtensionRegistry.h; path = objectivec/GPBExtensionRegistry.h; sourceTree = ""; }; + 7DF524EA9012A4ACFCAD0BF6C7247299 /* FIRInstanceIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenStore.h; path = Firebase/InstanceID/FIRInstanceIDTokenStore.h; sourceTree = ""; }; + 7DF716A590C33DA0E5141543D157C552 /* CLSAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSAttributes.h; path = iOS/Crashlytics.framework/Headers/CLSAttributes.h; sourceTree = ""; }; + 7E51F53C43C26EC84AD204A2DF58797C /* NSError+FIRMessaging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+FIRMessaging.m"; path = "Firebase/Messaging/NSError+FIRMessaging.m"; sourceTree = ""; }; + 7E542A623F5A954B3F4D243CF8A4FB46 /* NSError+FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+FIRInstanceID.h"; path = "Firebase/InstanceID/NSError+FIRInstanceID.h"; sourceTree = ""; }; + 7E629EB70356C8FA1AD9781584EA8374 /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m"; sourceTree = ""; }; + 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BonMot.xcconfig; sourceTree = ""; }; + 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.xcconfig; sourceTree = ""; }; + 7F492B106E8EB1E2C72059F4CEC2ADF4 /* GULAppDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler_Private.h; path = GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h; sourceTree = ""; }; + 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.xcconfig; sourceTree = ""; }; + 7F9F3C7A180A25601F10CA6EDA5435A1 /* Alamofire.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Alamofire.modulemap; sourceTree = ""; }; + 7FF09D8EFD37D437525F039619D3D763 /* GoogleUtilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleUtilities.modulemap; sourceTree = ""; }; + 807724545CC9FBB3B33672198DD057ED /* GULUserDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULUserDefaults.h; path = GoogleUtilities/UserDefaults/Private/GULUserDefaults.h; sourceTree = ""; }; + 809A9FA0958DAAB72D85475C1510B28C /* Api.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = objectivec/google/protobuf/Api.pbobjc.m; sourceTree = ""; }; + 80F2752CD15387DAD8075D0DE08C9A48 /* SimulatorStatusMagic.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SimulatorStatusMagic.modulemap; sourceTree = ""; }; + 814B71C2E085A900096EC6AECF6B4CE3 /* GPBWireFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBWireFormat.m; path = objectivec/GPBWireFormat.m; sourceTree = ""; }; + 82350E48404736EC458CE6073EFD26C3 /* IBGFeatureRequests.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGFeatureRequests.h; path = Instabug.framework/Headers/IBGFeatureRequests.h; sourceTree = ""; }; + 8239448521ADE6944ED02A4E4E8F83C5 /* GULNetworkURLSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkURLSession.h; path = GoogleUtilities/Network/Private/GULNetworkURLSession.h; sourceTree = ""; }; + 829A957DF3BA4C53A538E446773D71B8 /* AppInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppInfo.swift; path = Pod/Classes/AboutView/AppInfo.swift; sourceTree = ""; }; + 829D6EBA77079A9CFF95E76253E1B175 /* fr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fr.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj"; sourceTree = ""; }; + 82C3962E95811D63FBFBD722F2BD0204 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; + 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 842142B2B14A0BA4AFCC17CBAC0F7C98 /* pl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pl.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj"; sourceTree = ""; }; + 846244C0EC47A8A7BE9B1E2506F77C50 /* FIRMessagingRmq2PersistentStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRmq2PersistentStore.h; path = Firebase/Messaging/FIRMessagingRmq2PersistentStore.h; sourceTree = ""; }; + 8466929A49CE3221978EB36183FD35BA /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUtilities_PackagePrivate.h; path = objectivec/GPBUtilities_PackagePrivate.h; sourceTree = ""; }; + 8487A57EC520F91735649B13CF1455E4 /* FIRInstanceIDCheckinPreferences+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDCheckinPreferences+Internal.h"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h"; sourceTree = ""; }; + 849FE1C62D5BADA93D12508A10FFB88A /* FIRMessagingPubSubRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPubSubRegistrar.h; path = Firebase/Messaging/FIRMessagingPubSubRegistrar.h; sourceTree = ""; }; + 84DA61DFF1F0980689DC3F498047D530 /* SimulatorStatusMagic-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SimulatorStatusMagic-Info.plist"; sourceTree = ""; }; + 86773016D7292DB1077AB6ED22B7CAE1 /* Anchorage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Anchorage-Info.plist"; sourceTree = ""; }; + 86B9F61513C3569FB8F5F80587BD0802 /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = Firebase/Core/Private/FIRErrorCode.h; sourceTree = ""; }; + 8750CA9FEFAD9991DCE303273D306351 /* nanopb-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-prefix.pch"; sourceTree = ""; }; + 88B5959D5B7A3E36DDEF6EA561F00502 /* FIRInstanceIDAPNSInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAPNSInfo.m; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.m; sourceTree = ""; }; + 88C8386A2D3A8315518D7FC2CF01A15B /* FIRMessagingTopicOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingTopicOperation.h; path = Firebase/Messaging/FIRMessagingTopicOperation.h; sourceTree = ""; }; + 88F89AA47577A480D576C38E3EDFADAA /* Swiftilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Swiftilities-umbrella.h"; sourceTree = ""; }; + 8942E740881A6372C900E36D68EAF4CB /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBCodedOutputStream.m; path = objectivec/GPBCodedOutputStream.m; sourceTree = ""; }; + 894FB1F3B5CAA20D3A8E5DA58FA415A3 /* OHPathHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHPathHelpers.m; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m; sourceTree = ""; }; + 89A489E0FEA5C5815748A7017DDB2666 /* FirebaseMessaging.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseMessaging.modulemap; sourceTree = ""; }; + 8A10B633A7F6F7DB8565FCD54B2F6015 /* GPBDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBDictionary.m; path = objectivec/GPBDictionary.m; sourceTree = ""; }; + 8A2450A9AC3AEDEE3814CEC1893EBE3F /* Protobuf-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Protobuf-umbrella.h"; sourceTree = ""; }; + 8A467A3E9E3137B15241AA445AAA69D3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; + 8B0B7D7F03E7C5408A9FEDE21398424D /* Pods_PRODUCTNAME_PRODUCTNAMETests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PRODUCTNAME_PRODUCTNAMETests.framework; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8B4A5B8EBEA544128E7C93E89A933ACE /* GPBRootObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBRootObject.m; path = objectivec/GPBRootObject.m; sourceTree = ""; }; + 8BCBB2D56D50E44BD77F0169A7F75E7B /* FIRMessagingRmqManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRmqManager.h; path = Firebase/Messaging/FIRMessagingRmqManager.h; sourceTree = ""; }; + 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sourcery.xcconfig; sourceTree = ""; }; + 8C4EB1163B98FFAB7C42AB21C3ACF776 /* Ligatures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Ligatures.swift; path = Sources/Ligatures.swift; sourceTree = ""; }; + 8CC134AECB569C629CF74E270D3E8FC3 /* Pods-PRODUCTNAME.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.debug.xcconfig"; sourceTree = ""; }; + 8E5AF5D638A5E46AC1F536B0D9FC686E /* FIRMessaging_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessaging_Private.h; path = Firebase/Messaging/FIRMessaging_Private.h; sourceTree = ""; }; + 8EA90B335493CD691AF6F92A19615597 /* FIRAnalyticsConnector.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FIRAnalyticsConnector.framework; path = Frameworks/FIRAnalyticsConnector.framework; sourceTree = ""; }; + 8F00E32E42A1E8D5237611B57EB97BFC /* FIRInstanceIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStore.m; path = Firebase/InstanceID/FIRInstanceIDStore.m; sourceTree = ""; }; + 8F4E12C03F40438969454920C49D2013 /* FIRInstanceID_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID_Private.h; path = Firebase/InstanceID/Private/FIRInstanceID_Private.h; sourceTree = ""; }; + 8F63F7236794D312ACB1F32E2BE55CA4 /* Pods-PRODUCTNAME-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PRODUCTNAME-umbrella.h"; sourceTree = ""; }; + 8FA9AF149F192E34E86DF398F93B6819 /* Tab.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tab.swift; path = Sources/Tab.swift; sourceTree = ""; }; + 8FD395C6B080D05AA0E9B521C84DE95C /* FirebaseInstanceID-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstanceID-dummy.m"; sourceTree = ""; }; + 900494C92D1BC8DD44B41A1E185446A2 /* FIRComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponent.m; path = Firebase/Core/FIRComponent.m; sourceTree = ""; }; + 91A527A11C0F5C0E19DEF21E7B9C7F7E /* AcknowledgementsListViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementsListViewController.swift; path = Pod/Classes/Acknowledgements/AcknowledgementsListViewController.swift; sourceTree = ""; }; + 9217346EC5CA9E35B7D5CC7A1AC82A9B /* zh-Hans.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hans.lproj"; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj"; sourceTree = ""; }; + 9221AE50CB51C7E8CD93A956CC3EA7C2 /* GULNetworkConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkConstants.h; path = GoogleUtilities/Network/Private/GULNetworkConstants.h; sourceTree = ""; }; + 92B3A83AF7CBD24CFB27352A8A473464 /* NSURLRequest+HTTPBodyTesting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSURLRequest+HTTPBodyTesting.h"; path = "OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.h"; sourceTree = ""; }; + 92F4855C80835F853383873CD1CB78B4 /* FIRMessagingRmqManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRmqManager.m; path = Firebase/Messaging/FIRMessagingRmqManager.m; sourceTree = ""; }; + 935548E336DB715970FA91771AE5D568 /* Fabric.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Fabric.h; path = iOS/Fabric.framework/Headers/Fabric.h; sourceTree = ""; }; + 9435CEF7CA7BCE866E215F71262E51F6 /* HairlineView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HairlineView.swift; path = Pod/Classes/HairlineView/HairlineView.swift; sourceTree = ""; }; + 9457CFFC68284D195CF10F91CD0AB794 /* Tab+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Tab+Adaptive.swift"; path = "Sources/UIKit/Tab+Adaptive.swift"; sourceTree = ""; }; + 949C61608ACEFB9BB47A141E428D5CED /* FIRMessagingPubSub.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPubSub.m; path = Firebase/Messaging/FIRMessagingPubSub.m; sourceTree = ""; }; + 94F243E68DA74E3EF1064781840A6375 /* SDStatusBarOverriderPost10_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost10_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost10_0.m; sourceTree = ""; }; + 95728BB595EBF3C2595CF132C9C7AAAC /* Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh"; sourceTree = ""; }; + 966E61D7CDD4B8F269B4C52F6C9D4E6F /* GULNSData+zlib.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULNSData+zlib.h"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.h"; sourceTree = ""; }; + 968AD6C6067177F3FFBF4E22B5D62AFA /* Priority.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Priority.swift; path = Source/Priority.swift; sourceTree = ""; }; + 97EFF3947D869F0FC7D7D08A1B3B0A6E /* FIROptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROptions.m; path = Firebase/Core/FIROptions.m; sourceTree = ""; }; + 986EF3488689CACCCB183285A1909D6A /* FIRMessagingCodedInputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingCodedInputStream.m; path = Firebase/Messaging/FIRMessagingCodedInputStream.m; sourceTree = ""; }; + 98DE82806BC35C7A7C3ACBCF0C7B379F /* FIRMessagingAnalytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingAnalytics.h; path = Firebase/Messaging/FIRMessagingAnalytics.h; sourceTree = ""; }; + 990D5BCA382BD9D9D2C3C1E291F2B135 /* FIRComponentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentType.m; path = Firebase/Core/FIRComponentType.m; sourceTree = ""; }; + 9917CC431DC36BB3D118B1AA7A204319 /* es.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = es.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj"; sourceTree = ""; }; + 994790A4BDFB35C5FEEEB4B16ACD0073 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = Firebase/Core/Private/FIRComponentType.h; sourceTree = ""; }; + 9A572C6721447ABE0F589A4004BA6EFA /* Pods-PRODUCTNAME-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PRODUCTNAME-dummy.m"; sourceTree = ""; }; + 9A68AA6C83230BBFED7CC97DA09A987B /* FirebaseMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseMessaging.h; path = Firebase/Messaging/Public/FirebaseMessaging.h; sourceTree = ""; }; + 9AAD5AF881A90E6C8ABB964271CD3D7F /* FIRMessagingAnalytics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingAnalytics.m; path = Firebase/Messaging/FIRMessagingAnalytics.m; sourceTree = ""; }; + 9B49BB3E350F98DF8781264F7BB9D61B /* FIRInstanceIDCombinedHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCombinedHandler.h; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.h; sourceTree = ""; }; + 9B7024F62947EF6E2C6FB6CD5B34E2ED /* FIRConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRConfiguration.m; path = Firebase/Core/FIRConfiguration.m; sourceTree = ""; }; + 9BE96B90011674F188BAA0598BD91B53 /* OHHTTPStubs.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubs.m; path = OHHTTPStubs/Sources/OHHTTPStubs.m; sourceTree = ""; }; + 9C8948FFD9D354F2001C98CEE8B45E08 /* FIRMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessaging.h; path = Firebase/Messaging/Public/FIRMessaging.h; sourceTree = ""; }; + 9D4DE2FA59344D4592D75A8D5A4137CE /* UIKit+AdaptableTextContainerSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIKit+AdaptableTextContainerSupport.swift"; path = "Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift"; sourceTree = ""; }; + 9D75377169BF1143EF206F74484FC1F0 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = objectivec/google/protobuf/Timestamp.pbobjc.m; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9E5B2FEF0A506CDAE2D10761BE2F376E /* FeedbackPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FeedbackPresenter.swift; path = Pod/Classes/AboutView/FeedbackPresenter.swift; sourceTree = ""; }; - 9F0B5CEE4220ED99753109FF0C4554D4 /* GAIDictionaryBuilder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAIDictionaryBuilder.h; path = Sources/GAIDictionaryBuilder.h; sourceTree = ""; }; - 9FDDC29E87B92F93E44BCD9BE2EDED7B /* Alamofire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Alamofire.framework; path = Alamofire.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A0C489DAD9337929C5181A707028C871 /* Pods-Services-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Services-acknowledgements.plist"; sourceTree = ""; }; - A3AE46141D0D4C9B24ABA5B528FA5352 /* Pods-PRODUCTNAME-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PRODUCTNAME-acknowledgements.markdown"; sourceTree = ""; }; - A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAnalytics.xcconfig; sourceTree = ""; }; - A6A3C66135761B8589F2EEC25372EA62 /* SDStatusBarOverriderPost10_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost10_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost10_0.m; sourceTree = ""; }; - A71071A87AEBBA036F448F39A4AF7226 /* OHHTTPStubsResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsResponse.h; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.h; sourceTree = ""; }; - A789E28B8BC1DFFB04379D3F52042939 /* Pods-PRODUCTNAME-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-Info.plist"; sourceTree = ""; }; - A80FB9309074DE8E3648C328313041C2 /* KeychainAccess-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KeychainAccess-umbrella.h"; sourceTree = ""; }; - A946DCC1815CEAD36C91124C6248CA37 /* OHHTTPStubs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = OHHTTPStubs.framework; path = OHHTTPStubs.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - AAAAC152788B64C89E923A18277EBA4C /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Request.swift; path = Source/Request.swift; sourceTree = ""; }; - ACA3A4AF812957B34242F8835CB3ECFB /* UIWindow+RootViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+RootViewController.swift"; path = "Pod/Classes/RootViewController/UIWindow+RootViewController.swift"; sourceTree = ""; }; - AD4EA92B56734A8CA71BFB65EC5996C7 /* OHHTTPStubsResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsResponse.m; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.m; sourceTree = ""; }; - AD5BD87CBD27D13BE3B64470D2514F3E /* Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Compatibility.h; path = OHHTTPStubs/Sources/Compatibility.h; sourceTree = ""; }; - ADA69A7B37937B271062924B815424C5 /* UIColor+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIColor+Helpers.swift"; path = "Pod/Classes/ColorHelpers/UIColor+Helpers.swift"; sourceTree = ""; }; - B0F981FC5A6AC94677657E5363CB9F6E /* Swiftilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Swiftilities-Info.plist"; sourceTree = ""; }; - B4C9173AAD69C5F900F070C2DC393F90 /* Alamofire-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Alamofire-Info.plist"; sourceTree = ""; }; - B4E5336742C14FD6B50FD57C94F7E2EF /* Pods-PRODUCTNAME.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.develop.xcconfig"; sourceTree = ""; }; - B576D87C99AA3051DC9EFE733505C01B /* Anchorage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Anchorage-umbrella.h"; sourceTree = ""; }; - B633536FE6BDE55D4B91A7795F4FF80E /* Alamofire-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-prefix.pch"; sourceTree = ""; }; - B67E5A3B83075128A1543C2893FF8978 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; - B68AFDFA486327E986AA02A5299A8997 /* SDStatusBarOverriderPost10_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost10_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost10_3.m; sourceTree = ""; }; - B7268C56B15EE03AC9317CFB3648AE37 /* DispatchQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Alamofire.swift"; path = "Source/DispatchQueue+Alamofire.swift"; sourceTree = ""; }; - B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BonMot.xcconfig; sourceTree = ""; }; - B81E944F8B0AEB55DC7130BCF5D0265E /* FieldValidator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FieldValidator.swift; path = Pod/Classes/Forms/FieldValidator.swift; sourceTree = ""; }; - B85FB8C2D1A62E349160A5994FAD2E98 /* Pods-Services-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Services-acknowledgements.markdown"; sourceTree = ""; }; - B897A3FA47CC0821B4DB6D3C2B7E99CB /* Pods-Services-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Services-umbrella.h"; sourceTree = ""; }; - B921E0CBB6CCB74325890A14EE6C3F5B /* AppInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppInfo.swift; path = Pod/Classes/AboutView/AppInfo.swift; sourceTree = ""; }; - BA2995A05285EE6DED3FEEA5F13AACF4 /* SDStatusBarOverriderPost11_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost11_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost11_0.m; sourceTree = ""; }; - BC68423B5D03B01844BE44E57D3105DF /* CoreDataStack.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CoreDataStack.swift; path = Pod/Classes/CoreDataStack/CoreDataStack.swift; sourceTree = ""; }; - BC96213BE7B62B82294197DF2AC70DA8 /* SimulatorStatusMagic-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SimulatorStatusMagic-umbrella.h"; sourceTree = ""; }; - BCDA5E72258FCCDB8B342B3D19FF405C /* Anchorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Anchorage.swift; path = Source/Anchorage.swift; sourceTree = ""; }; - BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = OHHTTPStubs.xcconfig; sourceTree = ""; }; - BECFB2D89D8B3332F5F17C1CE83D7E8F /* UITableView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITableView+Extensions.swift"; path = "Pod/Classes/TableViewHelpers/UITableView+Extensions.swift"; sourceTree = ""; }; - BEED7AEAC6B377BEABA32BCA6E029D06 /* OHPathHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHPathHelpers.h; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h; sourceTree = ""; }; - BF48041B0643C6B8315D6381008DEE3C /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Source/SessionDelegate.swift; sourceTree = ""; }; - C3BD4ED7910EC78F54E9906021EAC11E /* SDStatusBarOverriderPost9_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost9_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost9_3.m; sourceTree = ""; }; - C427306A6F25ED154EDC741171B0672D /* CGFloat+DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CGFloat+DeviceSize.swift"; path = "Pod/Classes/DeviceSize/CGFloat+DeviceSize.swift"; sourceTree = ""; }; - C42BE2BD8793574C8CCFF047DE230880 /* AFError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AFError.swift; path = Source/AFError.swift; sourceTree = ""; }; - C56086F41BE1C76C0A2162242BE882BB /* ViewControllerLifecycleBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ViewControllerLifecycleBehavior.swift; path = Pod/Classes/Lifecycle/Framework/ViewControllerLifecycleBehavior.swift; sourceTree = ""; }; - C580B89A921E19C037BD54E71FF73A6A /* BonMot-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BonMot-umbrella.h"; sourceTree = ""; }; - C615B52490F87ADAB2878CBBA62A49EE /* SDStatusBarManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarManager.h; path = SDStatusBarManager/SDStatusBarManager.h; sourceTree = ""; }; - C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sourcery.xcconfig; sourceTree = ""; }; - C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = KeychainAccess.xcconfig; sourceTree = ""; }; - C7ADD80B33BD1D3965F9685D011E653B /* NSURLRequest+HTTPBodyTesting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSURLRequest+HTTPBodyTesting.h"; path = "OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.h"; sourceTree = ""; }; - C8A1F76AAB60389D3C093AC1A50BF0A9 /* Platform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Platform.swift; path = Sources/Platform.swift; sourceTree = ""; }; - CAC7B89760289277486CBA8E128C3E83 /* IBGReplies.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGReplies.h; path = Instabug.framework/Headers/IBGReplies.h; sourceTree = ""; }; - CACC82C9360F0099F26C79E3B2059185 /* BonMot-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BonMot-dummy.m"; sourceTree = ""; }; - CB38C12AE406FDC85937CCF35845E787 /* AccessibilityHelpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityHelpers.swift; path = Pod/Classes/AccessibilityHelpers/AccessibilityHelpers.swift; sourceTree = ""; }; - CBA24296CBFCC1AB1BC5AB37A4F7BD49 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; }; - CC6991AC15FB6E796C0D2D216AB1B409 /* DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeviceSize.swift; path = Pod/Classes/DeviceSize/DeviceSize.swift; sourceTree = ""; }; - CDE8ACA571ED75517D0E41EB2D0AE086 /* Tracking.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tracking.swift; path = Sources/Tracking.swift; sourceTree = ""; }; - CE1ABD0449009E446A4D3F9A93FC4DEB /* Internal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Internal.swift; path = Source/Internal.swift; sourceTree = ""; }; - CFD134FCA91FFE97E31F5E29CF515503 /* Log.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Log.swift; path = Pod/Classes/Logging/Log.swift; sourceTree = ""; }; - CFDD87526BDBCFE4DDF38D11B28728D8 /* CLSReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSReport.h; path = iOS/Crashlytics.framework/Headers/CLSReport.h; sourceTree = ""; }; - D028177281860E86C9025064AAD7903C /* Swiftilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Swiftilities.modulemap; sourceTree = ""; }; - D1715D98301B1F97137AD0E551489F6C /* OHHTTPStubs-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-umbrella.h"; sourceTree = ""; }; - D6A7ADC89E5C649F8CA13967D02858A9 /* IBGCrashReporting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGCrashReporting.h; path = Instabug.framework/Headers/IBGCrashReporting.h; sourceTree = ""; }; - D7092F8161B004CC1F80E7A6C21E1782 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown"; sourceTree = ""; }; - D7C275922D24E9A31A6B5A520B32C8CD /* GAIEcommercePromotion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GAIEcommercePromotion.h; path = Sources/GAIEcommercePromotion.h; sourceTree = ""; }; - D80B127AD7C7BB100CC551B493D3D794 /* UIKit+AdaptableTextContainerSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIKit+AdaptableTextContainerSupport.swift"; path = "Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift"; sourceTree = ""; }; - D8D0E31FC29539DB63B7901E4B473483 /* SDStatusBarOverriderPost9_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost9_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost9_0.h; sourceTree = ""; }; - D90A96D40B7CB86171BF8078F9CA3D9A /* FormattedTextField.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FormattedTextField.swift; path = Pod/Classes/FormattedTextField/FormattedTextField.swift; sourceTree = ""; }; - D9CA18D0EBAA000A7E08DB708924C2B9 /* UIKit+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIKit+Helpers.swift"; path = "Sources/UIKit/UIKit+Helpers.swift"; sourceTree = ""; }; - DA0914676ACB3881C960293BB680AECD /* Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig"; sourceTree = ""; }; - DB96B984A6D557536E37D38A9C71887F /* TaskDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskDelegate.swift; path = Source/TaskDelegate.swift; sourceTree = ""; }; - DC14BE78C6ADC4A456ED440DA669B424 /* AdaptiveStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptiveStyle.swift; path = Sources/UIKit/AdaptiveStyle.swift; sourceTree = ""; }; - DCB901DB5CF0F009F87153156EFD3FAB /* CLSLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSLogging.h; path = iOS/Crashlytics.framework/Headers/CLSLogging.h; sourceTree = ""; }; - DD20F29EDEBA60AED25F95B2CE422567 /* Pods-Services.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.sprint.xcconfig"; sourceTree = ""; }; - DE0E7C617CC610A75A05A76F56C75DB0 /* AccessibilityHeadingLevel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityHeadingLevel.swift; path = Sources/AccessibilityHeadingLevel.swift; sourceTree = ""; }; - DF1BC0A1B0C287F0903058BAEC132BEA /* NSAttributedString+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+Adaptive.swift"; path = "Sources/UIKit/NSAttributedString+Adaptive.swift"; sourceTree = ""; }; - DFA0BCDC716C3C2DF6E46612791CA5FD /* SDStatusBarOverriderPre8_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPre8_3.h; path = SDStatusBarManager/SDStatusBarOverriderPre8_3.h; sourceTree = ""; }; - DFB0EC7EBB399F7D5A85850FD00CE2C4 /* SDStatusBarOverriderPre8_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPre8_3.m; path = SDStatusBarManager/SDStatusBarOverriderPre8_3.m; sourceTree = ""; }; - DFD8BF8FFA442A208B702F283FFCD45E /* CLSStackFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSStackFrame.h; path = iOS/Crashlytics.framework/Headers/CLSStackFrame.h; sourceTree = ""; }; - E172436BEA1AA48D80B4772E292D7D6F /* Pods-Services.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.debug.xcconfig"; sourceTree = ""; }; - E17CAFC73159C1C1EB2C35ECFFDCF234 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist"; sourceTree = ""; }; - E17F1FA7E71417208B484A6B4798DDD6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - E37EC6963507772140141310564C96A7 /* Alamofire-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-umbrella.h"; sourceTree = ""; }; - E382E277E58CBB6C6EA0E889BBC6490F /* IBGTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGTypes.h; path = Instabug.framework/Headers/IBGTypes.h; sourceTree = ""; }; - E3C4C1F6B36E0BECB296C1483D026F54 /* OHHTTPStubs-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-prefix.pch"; sourceTree = ""; }; - E649566A94614794DCA667332EDBB277 /* Anchorage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Anchorage-Info.plist"; sourceTree = ""; }; - E6CDD1E32FFC400D46C2622FA77E0AA1 /* libGoogleAnalytics.a */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = archive.ar; name = libGoogleAnalytics.a; path = Libraries/libGoogleAnalytics.a; sourceTree = ""; }; - E6F2B0D3C4AE001AA8D39C968195273A /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkReachabilityManager.swift; path = Source/NetworkReachabilityManager.swift; sourceTree = ""; }; - E74DC75AECA924D9AA03636808FE7BDF /* SDStatusBarOverrider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverrider.h; path = SDStatusBarManager/SDStatusBarOverrider.h; sourceTree = ""; }; - E7FE233BF7FEEB9A8A795679328F0C82 /* Pods-PRODUCTNAME-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PRODUCTNAME-umbrella.h"; sourceTree = ""; }; - E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftGen.xcconfig; sourceTree = ""; }; - EB19F16C37CD2E91D6E593747C7AF54F /* OHHTTPStubs-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "OHHTTPStubs-dummy.m"; sourceTree = ""; }; - EC1AF230CF867C88C770CE9C374EA4A9 /* NSLayoutAnchor+MultiplierConstraints.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutAnchor+MultiplierConstraints.swift"; path = "Source/NSLayoutAnchor+MultiplierConstraints.swift"; sourceTree = ""; }; - EE18F1B83B66E2F8033DD4F4C792ED8A /* OHHTTPStubsSwift.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OHHTTPStubsSwift.swift; path = OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift; sourceTree = ""; }; - F0031BCA4B2C3DB8E91F1EECDFBE1285 /* Instabug.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Instabug.h; path = Instabug.framework/Headers/Instabug.h; sourceTree = ""; }; - F39A38B8C8A7A15B87AEB9C6DE99AA9F /* Fabric.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Fabric.h; path = iOS/Fabric.framework/Headers/Fabric.h; sourceTree = ""; }; - F3B6C1F52D3C489842038C172FF057F2 /* CLSAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSAttributes.h; path = iOS/Crashlytics.framework/Headers/CLSAttributes.h; sourceTree = ""; }; - F562BB9A7020F3CBCE41AE3A3CB94883 /* Pods_PRODUCTNAME_PRODUCTNAMETests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PRODUCTNAME_PRODUCTNAMETests.framework; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - F8EB17459DA65ED2256E7DD16A25905C /* Pods-PRODUCTNAME.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.debug.xcconfig"; sourceTree = ""; }; - F91A8173C9C7657C0E2880FF9046516E /* KeychainAccess-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KeychainAccess-prefix.pch"; sourceTree = ""; }; - F9E56C55E5C3E4C28EBF213499DC13B2 /* SDStatusBarOverriderPost10_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost10_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost10_3.h; sourceTree = ""; }; - FA462C4F41ADFF2B1F485CA4D300A507 /* Keyboard.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Keyboard.swift; path = Pod/Classes/Keyboard/Keyboard.swift; sourceTree = ""; }; - FB6C041C62D7A0FC5904F4CA72030FC3 /* TailoredSwiftTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TailoredSwiftTextView.swift; path = Pod/Classes/Views/Textview/TailoredSwiftTextView.swift; sourceTree = ""; }; - FBF2880E3762207FCA439FC5B3BFE9D1 /* UITextView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITextView+Extensions.swift"; path = "Pod/Classes/Views/Textview/UITextView+Extensions.swift"; sourceTree = ""; }; - FD0003595E56E3351A484C39D062FAA5 /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoding.swift; path = Source/ParameterEncoding.swift; sourceTree = ""; }; - FD33C68E323DA2EF0D6FAE8737B0BD1D /* Pods-PRODUCTNAME-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PRODUCTNAME-dummy.m"; sourceTree = ""; }; - FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.xcconfig; sourceTree = ""; }; - FF6FA5A59381E1B6E4E4C836E4DC3E8B /* UIView+Instabug.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+Instabug.h"; path = "Instabug.framework/Headers/UIView+Instabug.h"; sourceTree = ""; }; + 9E5694DFDF2C9E53E5A1BB537671493B /* Protobuf.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Protobuf.modulemap; sourceTree = ""; }; + 9E603AE6FAEA107641D9E8499AD28ACD /* Special.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Special.swift; path = Sources/Special.swift; sourceTree = ""; }; + 9EE85328C2AA2BE65AC5476B9A3A4B9A /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBRootObject_PackagePrivate.h; path = objectivec/GPBRootObject_PackagePrivate.h; sourceTree = ""; }; + 9EF280833555D9A6C3AB807C1BBEF193 /* FontFeatures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FontFeatures.swift; path = Sources/FontFeatures.swift; sourceTree = ""; }; + 9EF45F089BAE93FE828CD9688AA8CA8A /* KeychainAccess-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KeychainAccess-umbrella.h"; sourceTree = ""; }; + 9F64FB46C163A2D7EEDD531525ED4A3E /* FIRInstanceIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStore.h; path = Firebase/InstanceID/FIRInstanceIDStore.h; sourceTree = ""; }; + A0540CA217C994053589CECC283EFEE1 /* IBGSurvey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGSurvey.h; path = Instabug.framework/Headers/IBGSurvey.h; sourceTree = ""; }; + A1718A38D1F7426976B72AE548700F4E /* Pods-PRODUCTNAME-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PRODUCTNAME-resources.sh"; sourceTree = ""; }; + A23C1F66FE104A9AB25DB49ABA41F52E /* ResponseSerialization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResponseSerialization.swift; path = Source/ResponseSerialization.swift; sourceTree = ""; }; + A39DC1AB08D7C48D33B0213FC070EE91 /* CoreDataStack.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CoreDataStack.swift; path = Pod/Classes/CoreDataStack/CoreDataStack.swift; sourceTree = ""; }; + A3AA81B96ABF2101A80128229B5253C0 /* FIRInstanceIDUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDUtilities.h; path = Firebase/InstanceID/FIRInstanceIDUtilities.h; sourceTree = ""; }; + A45D8D0A1979A555EFB7FFB40FE9E3B3 /* Emphasis.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Emphasis.swift; path = Sources/Emphasis.swift; sourceTree = ""; }; + A48A79CAAFF110C87DF8BF807837AB83 /* FIRInstanceIDConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDConstants.m; path = Firebase/InstanceID/FIRInstanceIDConstants.m; sourceTree = ""; }; + A52569BDA16818151E3735016A95C16B /* UIView+Lookup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+Lookup.swift"; path = "Pod/Classes/Forms/UIView+Lookup.swift"; sourceTree = ""; }; + A64AD290563189B5EC09536986EEA27C /* GoogleUtilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-umbrella.h"; sourceTree = ""; }; + A668229ECF671E377647F4DE649FE2D9 /* GULSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSwizzler.m; path = GoogleUtilities/MethodSwizzler/GULSwizzler.m; sourceTree = ""; }; + A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstanceID.xcconfig; sourceTree = ""; }; + A78104E9B1CB747B9ACC895D21681C1E /* FirebaseCore-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCore-dummy.m"; sourceTree = ""; }; + A787CDE742CEB6FDF5F73F556D790691 /* SimulatorStatusMagic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SimulatorStatusMagic.framework; path = SimulatorStatusMagic.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A86060F6B97532F283FE392A2B356F3F /* FirebaseInstanceID-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstanceID-umbrella.h"; sourceTree = ""; }; + A9F6CAA436B21A9F893735228C041394 /* FIRBundleUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRBundleUtil.h; path = Firebase/Core/Private/FIRBundleUtil.h; sourceTree = ""; }; + AB8C0F48EBA2E62C0D0D696427AAF734 /* tr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = tr.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj"; sourceTree = ""; }; + ABF027D832F3CFAAE988298C13DB25CF /* FIRMessagingPubSubRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPubSubRegistrar.m; path = Firebase/Messaging/FIRMessagingPubSubRegistrar.m; sourceTree = ""; }; + AC024504A5C4B47AE13B434EA483D427 /* FIRErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRErrors.m; path = Firebase/Core/FIRErrors.m; sourceTree = ""; }; + AD145FCE40536EC56F550EF22AE3A2B3 /* GradientView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = Pod/Classes/Views/Gradient/GradientView.swift; sourceTree = ""; }; + AD183A51FD1FF965003291AC5F048C14 /* FIRMessagingConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingConnection.m; path = Firebase/Messaging/FIRMessagingConnection.m; sourceTree = ""; }; + AD4B1920B3B7BA2136B85A1738A0948B /* CLSLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSLogging.h; path = iOS/Crashlytics.framework/Headers/CLSLogging.h; sourceTree = ""; }; + AD72DEE352EC54E08A0DDA10EEDB3D49 /* SDStatusBarOverriderPost11_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost11_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost11_0.m; sourceTree = ""; }; + AD7C3AE346CDF47C559CAA1E29D38819 /* SDStatusBarOverriderPost9_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost9_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost9_3.m; sourceTree = ""; }; + AD9FCFD914EDA9CDBDE1BA40686E48E0 /* nanopb-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "nanopb-dummy.m"; sourceTree = ""; }; + ADB4B0347B4897392B2245F4E44D0AC1 /* GPBArray.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBArray.m; path = objectivec/GPBArray.m; sourceTree = ""; }; + ADD85DBCA961517182D229A520E707A7 /* KeychainAccess-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KeychainAccess-prefix.pch"; sourceTree = ""; }; + AF4C07CB531C2A20C075F1E2F27F9807 /* Pods-Services-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Services-dummy.m"; sourceTree = ""; }; + AF915886F12CE018C123DBCE8092ECC5 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist"; sourceTree = ""; }; + AF9BA9F1FCE9E687C9236562D28FBBF6 /* AdaptableTextContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptableTextContainer.swift; path = Sources/UIKit/AdaptableTextContainer.swift; sourceTree = ""; }; + AFE96786D662F36B014DB2976712E52D /* Compatibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatibility.swift; path = Pod/Classes/Compatibility/Compatibility.swift; sourceTree = ""; }; + B02CBEEE2EAAE48F5C59A0748E149382 /* FIRLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLoggerLevel.h; path = Firebase/Core/Public/FIRLoggerLevel.h; sourceTree = ""; }; + B0DF923FAF38D4B7E93295F4F7B7E252 /* OHHTTPStubsMethodSwizzling.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsMethodSwizzling.m; path = OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.m; sourceTree = ""; }; + B1032898B87F1DAFA71E47C7FCB2E415 /* BonMot.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BonMot.modulemap; sourceTree = ""; }; + B11A4E7961F768D0892E18D1649C5FE4 /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkReachabilityManager.swift; path = Source/NetworkReachabilityManager.swift; sourceTree = ""; }; + B1EEA6318B7652582ADC0248EF0E862A /* FIRMessagingDelayedMessageQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingDelayedMessageQueue.h; path = Firebase/Messaging/FIRMessagingDelayedMessageQueue.h; sourceTree = ""; }; + B2127ADF7134D22A7B41243F58B119B2 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBUnknownFieldSet.m; path = objectivec/GPBUnknownFieldSet.m; sourceTree = ""; }; + B2E98DDB0684CD0EED258207851A2A13 /* GULReachabilityChecker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULReachabilityChecker.m; path = GoogleUtilities/Reachability/GULReachabilityChecker.m; sourceTree = ""; }; + B348867894A4CE1D01EE3407670282AA /* FIRInstanceIDLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDLogger.m; path = Firebase/InstanceID/FIRInstanceIDLogger.m; sourceTree = ""; }; + B3B80947892AFE99F690D90E0E6F7A0C /* Empty.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = objectivec/google/protobuf/Empty.pbobjc.h; sourceTree = ""; }; + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleUtilities.framework; path = GoogleUtilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B4625D667AFBD9425C3A79449E05F451 /* FIRMessagingSyncMessageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingSyncMessageManager.m; path = Firebase/Messaging/FIRMessagingSyncMessageManager.m; sourceTree = ""; }; + B477F169CB917A9F07ABB3C6B0ED46BE /* Anchorage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Anchorage.framework; path = Anchorage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B4C8749E960A855A7C7965EC2BA8218A /* GtalkExtensions.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GtalkExtensions.pbobjc.m; path = Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m; sourceTree = ""; }; + B5391DB5CF7FE004619D4F1920521EA2 /* FIRConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfiguration.h; path = Firebase/Core/Public/FIRConfiguration.h; sourceTree = ""; }; + B53967F27884E26D24DE4B390642290C /* Duration.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = objectivec/google/protobuf/Duration.pbobjc.m; sourceTree = ""; }; + B5579787CFCE1BC97D5EF0CCEB731C04 /* Pods-PRODUCTNAME.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PRODUCTNAME.modulemap"; sourceTree = ""; }; + B5D090276832D4024D8B3A5568BEA4DE /* FIRMessagingReceiver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingReceiver.h; path = Firebase/Messaging/FIRMessagingReceiver.h; sourceTree = ""; }; + B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alamofire.xcconfig; sourceTree = ""; }; + B67FA446F6A78388566D90BDD02B2175 /* FIRMessagingPendingTopicsList.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPendingTopicsList.m; path = Firebase/Messaging/FIRMessagingPendingTopicsList.m; sourceTree = ""; }; + B7010FC71D49408694A41D0B4A22E831 /* AppCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenter.framework; path = "AppCenter-SDK-Apple/iOS/AppCenter.framework"; sourceTree = ""; }; + B732E75D7C970C6F08CDE5C6AFDF8702 /* zh-Hant.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hant.lproj"; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj"; sourceTree = ""; }; + B74880F26CD1B4204F6539C5B5502D2E /* EmbeddedTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmbeddedTransformation.swift; path = Sources/UIKit/EmbeddedTransformation.swift; sourceTree = ""; }; + B7873C854D420CA53D1BD7CE0700ACDC /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = objectivec/google/protobuf/FieldMask.pbobjc.m; sourceTree = ""; }; + B7A403AA64C0558925444F207EEADE76 /* OHHTTPStubs-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "OHHTTPStubs-dummy.m"; sourceTree = ""; }; + B7A5E48BA4D6DE7CABBE36B040019834 /* FIRMessagingSyncMessageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingSyncMessageManager.h; path = Firebase/Messaging/FIRMessagingSyncMessageManager.h; sourceTree = ""; }; + B7AD2BE9A6C9E2298E7917BF8FD6E425 /* it.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = it.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj"; sourceTree = ""; }; + B7B04D349B7F6EF4AB5D84952D2A53DE /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownFieldSet.h; path = objectivec/GPBUnknownFieldSet.h; sourceTree = ""; }; + B80D74D41E215EDC00F1A0D8245EC63E /* FIRInstanceIDTokenManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenManager.h; path = Firebase/InstanceID/FIRInstanceIDTokenManager.h; sourceTree = ""; }; + B8D3618FE4C32D4ADBE22D247745AB5F /* FIRInstanceIDBackupExcludedPlist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDBackupExcludedPlist.h; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h; sourceTree = ""; }; + B8E0195AADB4B77EBBA26DCB16A7ADB1 /* FIRMessagingDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingDefines.h; path = Firebase/Messaging/FIRMessagingDefines.h; sourceTree = ""; }; + B8E677CF6BD8B668E00639F75526D6FE /* UIImage+Tinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIImage+Tinting.swift"; path = "Pod/Classes/ImageHelpers/UIImage+Tinting.swift"; sourceTree = ""; }; + B94ED403343770A491208CD276342FF7 /* FIRInstanceIDTokenDeleteOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenDeleteOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m; sourceTree = ""; }; + BA59223CF8122E668F27A492727DA05A /* NSDictionary+FIRMessaging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+FIRMessaging.m"; path = "Firebase/Messaging/NSDictionary+FIRMessaging.m"; sourceTree = ""; }; + BAEE38A7456029D2435589A2AB61BB54 /* FIRInstanceIDLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDLogger.h; path = Firebase/InstanceID/FIRInstanceIDLogger.h; sourceTree = ""; }; + BB5DFE1F01AFD7800F073ECA808AD019 /* GPBRootObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBRootObject.h; path = objectivec/GPBRootObject.h; sourceTree = ""; }; + BBF0EE4B9DF20FB5E0DF535FED448A7E /* pb_decode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_decode.c; sourceTree = ""; }; + BC07246B7DD7857DA18E71CDAD1E01D4 /* FIRMessagingExtensionHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingExtensionHelper.h; path = Firebase/Messaging/Public/FIRMessagingExtensionHelper.h; sourceTree = ""; }; + BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftGen.xcconfig; sourceTree = ""; }; + BCDA99AA3900C0A75CF6AFE7E2BEF2A0 /* UIViewController+Lifecycle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Lifecycle.swift"; path = "Pod/Classes/Lifecycle/Framework/UIViewController+Lifecycle.swift"; sourceTree = ""; }; + BD6721E414F5E4895627210AFB5397AC /* Tracking.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tracking.swift; path = Sources/Tracking.swift; sourceTree = ""; }; + BDF0BD64F7D053FC261E77000D9D5B27 /* pb_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_encode.c; sourceTree = ""; }; + BE03FBD1AE757BEDE8D7B21466965FD1 /* NSDictionary+FIRMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+FIRMessaging.h"; path = "Firebase/Messaging/NSDictionary+FIRMessaging.h"; sourceTree = ""; }; + BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Swiftilities.xcconfig; sourceTree = ""; }; + C05C63DA5EBF6B109936FE6137E41737 /* Protobuf-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Protobuf-prefix.pch"; sourceTree = ""; }; + C0865174F215EE5541472B794F16EABD /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = objectivec/google/protobuf/SourceContext.pbobjc.m; sourceTree = ""; }; + C0CD839E48FC413F0F119BC2DF2B9FF2 /* SessionManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionManager.swift; path = Source/SessionManager.swift; sourceTree = ""; }; + C1364213BD031AD3BAD42D9E69571ADD /* FloatingPoint+Scale.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "FloatingPoint+Scale.swift"; path = "Pod/Classes/Math/FloatingPoint+Scale.swift"; sourceTree = ""; }; + C146F3AD61FC35B7C5ACADB293B2E5CF /* pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb.h; sourceTree = ""; }; + C1CD6931566B12098A093FE863131A16 /* Pods-PRODUCTNAME-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PRODUCTNAME-acknowledgements.markdown"; sourceTree = ""; }; + C2105C94812B6214B154F54DCEDB72AC /* Protobuf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Protobuf.framework; path = Protobuf.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C382C33DB25925C6186211ACF6C39C64 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = iOS/Fabric.framework; sourceTree = ""; }; + C392AFDD980E1C6B8554B9CCE3D4F95A /* Api.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = objectivec/google/protobuf/Api.pbobjc.h; sourceTree = ""; }; + C395986E3E5F5139E1E2D48B13C6B14A /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h"; sourceTree = ""; }; + C3BE33C9694478A1505C09DAF4276BAA /* GULAppEnvironmentUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppEnvironmentUtil.m; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m; sourceTree = ""; }; + C3C63D9CD07021084D0B9C31ED0A87AA /* FABAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FABAttributes.h; path = iOS/Fabric.framework/Headers/FABAttributes.h; sourceTree = ""; }; + C4060169D4E6873CF1EEF2A457AC3BD6 /* GPBUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBUtilities.m; path = objectivec/GPBUtilities.m; sourceTree = ""; }; + C40BAC08597BADB1064666DF2633CF2D /* SDStatusBarOverriderPost9_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost9_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost9_3.h; sourceTree = ""; }; + C4B85119F40EE2D53CF9459420F29B53 /* Pods-PRODUCTNAME.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME.appstore.xcconfig"; sourceTree = ""; }; + C5090975983CFFFD9CB40E0075C0D038 /* FIRInstanceIDKeyPairUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeyPairUtilities.m; path = Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m; sourceTree = ""; }; + C513955DA0F2FA1EC966C5DCB86267DE /* FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceID.m; path = Firebase/InstanceID/FIRInstanceID.m; sourceTree = ""; }; + C8268059830026F500EAD6383BB19F88 /* de.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = de.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj"; sourceTree = ""; }; + C84BD906EE42E9D43CBC7AE02AA3C2E3 /* Pods-Services.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Services.modulemap"; sourceTree = ""; }; + C88DB8688B47BE7D71F76B016AD52DA8 /* CurveProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CurveProvider.swift; path = Pod/Classes/Math/CurveProvider.swift; sourceTree = ""; }; + C9AE3F8C3C621FD1D0196F941D21A520 /* FirebaseMessaging-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseMessaging-umbrella.h"; sourceTree = ""; }; + CB5E05211C1CC74484FAD2D8B97F2437 /* IBGReplies.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGReplies.h; path = Instabug.framework/Headers/IBGReplies.h; sourceTree = ""; }; + CC67002EE29757073391E2064F1BD0E6 /* SDStatusBarOverriderPost12_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost12_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost12_0.m; sourceTree = ""; }; + CCE4EFC833EB090ACE8EAA95D8F1FB5D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + CCEEB9D362BE4122040EB3458E5009F9 /* FirebaseCore.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCore.modulemap; sourceTree = ""; }; + CD626DB394FDD0FF51FD012D20A334F0 /* SDStatusBarManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarManager.h; path = SDStatusBarManager/SDStatusBarManager.h; sourceTree = ""; }; + CDE72026FE9260A75C5737785EC261F2 /* OHHTTPStubs.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = OHHTTPStubs.modulemap; sourceTree = ""; }; + CE04EB1BD0E0D76A2673A8C0C3366119 /* FIRInstanceIDAuthKeyChain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthKeyChain.h; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h; sourceTree = ""; }; + CE2FA012779DEECE2BC6CC90C6E90407 /* FieldValidator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FieldValidator.swift; path = Pod/Classes/Forms/FieldValidator.swift; sourceTree = ""; }; + CE3DE9896DF364A9A8E70FBF3411CAAD /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = Firebase/Core/Private/FIRComponent.h; sourceTree = ""; }; + CEC8FF8EB54F243F318CF7B7F16F7278 /* FirebaseCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCore.h; path = Firebase/Core/Public/FirebaseCore.h; sourceTree = ""; }; + CF22CC9C8607DFE61523790B4E8080FC /* Compatability.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatability.swift; path = Source/Compatability.swift; sourceTree = ""; }; + CFF7EEAD7E8E9673C73848326928A6CA /* FIRInteropParameterNames.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInteropParameterNames.h; path = Interop/Analytics/Public/FIRInteropParameterNames.h; sourceTree = ""; }; + D2B4AA2B21255F7A6AA09F0E059321BF /* FIROptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptions.h; path = Firebase/Core/Public/FIROptions.h; sourceTree = ""; }; + D33CE071F3F3081B71DA145EC68A99E8 /* StylisticAlternates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StylisticAlternates.swift; path = Sources/StylisticAlternates.swift; sourceTree = ""; }; + D362F402CE5684297570016D7825F239 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Request.swift; path = Source/Request.swift; sourceTree = ""; }; + D3761200331DF867B994EFC4B6F238B8 /* CLSStackFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSStackFrame.h; path = iOS/Crashlytics.framework/Headers/CLSStackFrame.h; sourceTree = ""; }; + D3CAB6FE3C8CDCA5DBD77435EA5A937D /* IBGReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGReport.h; path = Instabug.framework/Headers/IBGReport.h; sourceTree = ""; }; + D436B935FFA96DDB042376CB5C11E29E /* FIRVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVersion.h; path = Firebase/Core/Private/FIRVersion.h; sourceTree = ""; }; + D46CD8B2E3B48A9900B0D54DC022F51E /* FIRIMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRIMessageCode.h; path = Firebase/InstanceID/FIRIMessageCode.h; sourceTree = ""; }; + D4DEEAB8E3E3054E7C33B89FFE01EF18 /* Alamofire-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-prefix.pch"; sourceTree = ""; }; + D50A2051D90DCC03E026A0A56A46F1E0 /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBRuntimeTypes.h; path = objectivec/GPBRuntimeTypes.h; sourceTree = ""; }; + D5DE97AD0E8D2A97E134344E7227B548 /* FIRInstanceIDAuthKeyChain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthKeyChain.m; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m; sourceTree = ""; }; + D5EB134AFDFBA28F3347C088E94F3AA1 /* GtalkExtensions.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GtalkExtensions.pbobjc.h; path = Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h; sourceTree = ""; }; + D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.xcconfig; sourceTree = ""; }; + D7500D2B23B7DC69CCA7B61577BEAD0D /* Protobuf-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Protobuf-dummy.m"; sourceTree = ""; }; + D7DEB68026091907EB2EBB5D82C47A00 /* FIRMessagingUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingUtilities.m; path = Firebase/Messaging/FIRMessagingUtilities.m; sourceTree = ""; }; + D7E5680FC53E7E9F3D5CDFD636890134 /* GPBCodedInputStream_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedInputStream_PackagePrivate.h; path = objectivec/GPBCodedInputStream_PackagePrivate.h; sourceTree = ""; }; + D7EC6B48A447510995672266B84A0112 /* Empty.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = objectivec/google/protobuf/Empty.pbobjc.m; sourceTree = ""; }; + D8D631A479FBF2CC1551FFD90D0D6CCF /* GULMutableDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULMutableDictionary.h; path = GoogleUtilities/Network/Private/GULMutableDictionary.h; sourceTree = ""; }; + D9011FC16F020AA7453970FDC70281F4 /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBArray_PackagePrivate.h; path = objectivec/GPBArray_PackagePrivate.h; sourceTree = ""; }; + D91C93EC98E43B5CACE58587FC5A08E4 /* FirebaseCore-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCore-Info.plist"; sourceTree = ""; }; + D9A9C2C923605432B520F3DCE9D1F43C /* nanopb.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = nanopb.modulemap; sourceTree = ""; }; + DA1CB779343A19D8C026EA3A9FD492D0 /* OHHTTPStubsMethodSwizzling.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsMethodSwizzling.h; path = OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.h; sourceTree = ""; }; + DA2E57EB3CB3312081676A46F7238B24 /* AdaptiveStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptiveStyle.swift; path = Sources/UIKit/AdaptiveStyle.swift; sourceTree = ""; }; + DB1194551671BF12886B8DECFEC28149 /* FIRInstanceIDKeychain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeychain.m; path = Firebase/InstanceID/FIRInstanceIDKeychain.m; sourceTree = ""; }; + DB5BD78F6D7A28ACB840F946DCBA826F /* OHHTTPStubs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubs.h; path = OHHTTPStubs/Sources/OHHTTPStubs.h; sourceTree = ""; }; + DB6E2DA2A7458E3619DF8D70A1EE9011 /* FIRInstanceIDKeychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeychain.h; path = Firebase/InstanceID/FIRInstanceIDKeychain.h; sourceTree = ""; }; + DC604E06843C199B7238C7ECCDD65231 /* GULNetwork.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetwork.m; path = GoogleUtilities/Network/GULNetwork.m; sourceTree = ""; }; + DCF0EDF0E175A8ABAE1DC6C2A8C67270 /* Validation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Validation.swift; path = Source/Validation.swift; sourceTree = ""; }; + DD6A6E8BEA17526E69B7E7C440D290E2 /* UIWindow+RootViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+RootViewController.swift"; path = "Pod/Classes/RootViewController/UIWindow+RootViewController.swift"; sourceTree = ""; }; + DE16395C09D232F30431F9810A0872D2 /* IBGBugReporting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGBugReporting.h; path = Instabug.framework/Headers/IBGBugReporting.h; sourceTree = ""; }; + DE1C7DAA26B8EA104B1A50DE2EC3AF35 /* XMLBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XMLBuilder.swift; path = Sources/XMLBuilder.swift; sourceTree = ""; }; + DE6910A0DE802228534590DFC11D90C2 /* FIRInstanceIDCheckinStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinStore.h; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.h; sourceTree = ""; }; + DEE2591C629B8D1D99F7EB621AFE24BA /* CubicBezier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CubicBezier.swift; path = Pod/Classes/Math/CubicBezier.swift; sourceTree = ""; }; + DFDA0DE503139F615A5FB983A7BAFD1A /* en.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = en.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj"; sourceTree = ""; }; + E02A8313137BB858673B63F616E21827 /* FIRAnalyticsInteropListener.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsInteropListener.h; path = Interop/Analytics/Public/FIRAnalyticsInteropListener.h; sourceTree = ""; }; + E036B66F0200BB21E6A3C50B4A98D7C8 /* UIColor+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIColor+Helpers.swift"; path = "Pod/Classes/ColorHelpers/UIColor+Helpers.swift"; sourceTree = ""; }; + E07B09F7C15576A3A444C774F45026FA /* FontInspector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FontInspector.swift; path = Sources/FontInspector.swift; sourceTree = ""; }; + E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Crashlytics.xcconfig; sourceTree = ""; }; + E19C54CB57055FAC1B7EC1A332B36AE1 /* FIRMessagingPersistentSyncMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPersistentSyncMessage.h; path = Firebase/Messaging/FIRMessagingPersistentSyncMessage.h; sourceTree = ""; }; + E1FE7B5BE33FDB3387A107014CDD4C22 /* Platform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Platform.swift; path = Sources/Platform.swift; sourceTree = ""; }; + E274690FABF5774F0512B21622B9BAD0 /* GPBExtensionInternals.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionInternals.m; path = objectivec/GPBExtensionInternals.m; sourceTree = ""; }; + E27982EA462CEA4BDA8EC7253E091FB9 /* FIRInteropEventNames.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInteropEventNames.h; path = Interop/Analytics/Public/FIRInteropEventNames.h; sourceTree = ""; }; + E2B37DD9690B667E67C7B749014FDAE6 /* FIRMessagingLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingLogger.h; path = Firebase/Messaging/FIRMessagingLogger.h; sourceTree = ""; }; + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCore.framework; path = FirebaseCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2E3405DF921FD6575E7698CA8B86D62 /* FIRInstanceIDCheckinPreferences.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences.h; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h; sourceTree = ""; }; + E2FDAAF328CFC1916BD31D012F33FA11 /* CGSize+DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CGSize+DeviceSize.swift"; path = "Pod/Classes/DeviceSize/CGSize+DeviceSize.swift"; sourceTree = ""; }; + E32BE18C7E79232857089AE39A09A626 /* ANSCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ANSCompatibility.h; path = iOS/Crashlytics.framework/Headers/ANSCompatibility.h; sourceTree = ""; }; + E3AE805A7D220717142177291A6563DD /* FIRMessagingRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRegistrar.m; path = Firebase/Messaging/FIRMessagingRegistrar.m; sourceTree = ""; }; + E458A4DC6C3E79475F17EE8A2379E327 /* pb_common.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_common.c; sourceTree = ""; }; + E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Fabric.xcconfig; sourceTree = ""; }; + E4A4ECCE028DEB376DB17F98A1E4451E /* NSAttributedString+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+Adaptive.swift"; path = "Sources/UIKit/NSAttributedString+Adaptive.swift"; sourceTree = ""; }; + E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Protobuf.xcconfig; sourceTree = ""; }; + E5A2D89B160FEBC3EA6D9A26612606E7 /* UIStackView+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIStackView+Helpers.swift"; path = "Pod/Classes/StackViewHelpers/UIStackView+Helpers.swift"; sourceTree = ""; }; + E689A6FA791FBDA83E75CA835495CE84 /* FIRMessagingRemoteNotificationsProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRemoteNotificationsProxy.m; path = Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m; sourceTree = ""; }; + E6B719E9A14C1E430887BE3B805CDDE2 /* BetterButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BetterButton.swift; path = Pod/Classes/BetterButton/BetterButton.swift; sourceTree = ""; }; + E6D0C984DDF42A7E6B78C3EAE3C981CB /* GPBCodedOutputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedOutputStream.h; path = objectivec/GPBCodedOutputStream.h; sourceTree = ""; }; + E735845AC66A0F18361E9CB0A620082A /* FIRMessagingDataMessageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingDataMessageManager.m; path = Firebase/Messaging/FIRMessagingDataMessageManager.m; sourceTree = ""; }; + E73E251E3CF96E1495BE3EC085526D94 /* GULNSData+zlib.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GULNSData+zlib.m"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.m"; sourceTree = ""; }; + E774767ADA7D8B661ACBB80E499003DD /* FIRMessaging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessaging.m; path = Firebase/Messaging/FIRMessaging.m; sourceTree = ""; }; + E7BDF86CE64C4E407EBF8A73A20C6EF3 /* GULNetworkLoggerProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkLoggerProtocol.h; path = GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h; sourceTree = ""; }; + E82C57A8834CD3A374E5E52A9DEBA80E /* GPBUnknownField.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBUnknownField.m; path = objectivec/GPBUnknownField.m; sourceTree = ""; }; + E862D618BF042EA8A06C94B566412A7A /* pb_encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_encode.h; sourceTree = ""; }; + E893CE5D8A792CBF4C835E33C903AB37 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = Firebase/Core/Private/FIRAppInternal.h; sourceTree = ""; }; + E8EE7F078656FABB8F6821D10FF994BB /* KeychainAccess.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = KeychainAccess.framework; path = KeychainAccess.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E90EB60C7D8B2CBCC777305E2D53F83F /* FIRInstanceIDVersionUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDVersionUtilities.m; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.m; sourceTree = ""; }; + EA144693E6BF8FE7CAC6E965241CE03D /* DefaultBehaviors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultBehaviors.swift; path = Pod/Classes/Lifecycle/Framework/DefaultBehaviors.swift; sourceTree = ""; }; + EA27AEAA510EE20594C0FCF896C53040 /* NSAttributedString+BonMot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+BonMot.swift"; path = "Sources/NSAttributedString+BonMot.swift"; sourceTree = ""; }; + EA44C89EDF2C4365821C353514E832DF /* FIRInstanceIDKeyPairStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeyPairStore.h; path = Firebase/InstanceID/FIRInstanceIDKeyPairStore.h; sourceTree = ""; }; + EC198B2667B7ACBED262624C674F40C0 /* FIRInstanceIDStringEncoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStringEncoding.m; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.m; sourceTree = ""; }; + EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = KeychainAccess.xcconfig; sourceTree = ""; }; + EC9B9847934B602C43CAC9AE7E2EBD36 /* AccessibilityHeadingLevel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityHeadingLevel.swift; path = Sources/AccessibilityHeadingLevel.swift; sourceTree = ""; }; + ECE318A98BEDBC9D92401EFDAE6EAC84 /* SDStatusBarOverriderPost11_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost11_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost11_0.h; sourceTree = ""; }; + ED06C07D733F97DE5A5F19FEBD086CF5 /* InstabugCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = InstabugCore.h; path = Instabug.framework/Headers/InstabugCore.h; sourceTree = ""; }; + ED75C449FDA4BD587531DFEE93D42918 /* FIRMessagingUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingUtilities.h; path = Firebase/Messaging/FIRMessagingUtilities.h; sourceTree = ""; }; + ED9E474AFCCD58C67C788DC90A8A9AD0 /* SDStatusBarOverrider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverrider.h; path = SDStatusBarManager/SDStatusBarOverrider.h; sourceTree = ""; }; + EEB3012499F8855E88664D9000D9DCE4 /* UIViewController+Deselection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Deselection.swift"; path = "Pod/Classes/Deselection/UIViewController+Deselection.swift"; sourceTree = ""; }; + EFBAAB841881AAAD3B071BA31361B288 /* GULReachabilityChecker+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULReachabilityChecker+Internal.h"; path = "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h"; sourceTree = ""; }; + F0821896A90AE916F84B3E580249644D /* FIRAppAssociationRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppAssociationRegistration.h; path = Firebase/Core/Private/FIRAppAssociationRegistration.h; sourceTree = ""; }; + F140B1E39A706719A3E80EF3EE95186D /* KeychainAccess-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "KeychainAccess-dummy.m"; sourceTree = ""; }; + F1EB3FA695D6D0C669DA36186435E474 /* FIRInstanceIDUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDUtilities.m; path = Firebase/InstanceID/FIRInstanceIDUtilities.m; sourceTree = ""; }; + F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseMessaging.xcconfig; sourceTree = ""; }; + F2181E7978D4D5EB57672242678285CA /* OHHTTPStubs+NSURLSessionConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubs+NSURLSessionConfiguration.m"; path = "OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m"; sourceTree = ""; }; + F33A6CC0B7DD266D5F442790D44ACD25 /* GPBDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDictionary.h; path = objectivec/GPBDictionary.h; sourceTree = ""; }; + F3787E17CA4EF4DC7B09E88A20DD9847 /* FirebaseCore-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCore-umbrella.h"; sourceTree = ""; }; + F44A4945BC33C7C54BB4A7520594B486 /* Image+Tinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Image+Tinting.swift"; path = "Sources/Image+Tinting.swift"; sourceTree = ""; }; + F4539DEEA1DD2E3E786DAB20A235E0B9 /* FIRInstanceIDKeyPairUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeyPairUtilities.h; path = Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h; sourceTree = ""; }; + F4E200831632A5DA6FE18A80ED063AA8 /* GPBMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBMessage.m; path = objectivec/GPBMessage.m; sourceTree = ""; }; + F582E21899CB1B7DD3C29A9B5AB73287 /* OHPathHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHPathHelpers.h; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h; sourceTree = ""; }; + F5C73B87D6F5DBC36EAF4F5A2C11C0D8 /* OHHTTPStubs-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "OHHTTPStubs-Info.plist"; sourceTree = ""; }; + F6B71CAF2E55E96D2C79702EA17AC62E /* GULNetworkURLSession.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkURLSession.m; path = GoogleUtilities/Network/GULNetworkURLSession.m; sourceTree = ""; }; + F6D1E9800DF9216163D243A25E5A7E22 /* FIRApp.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRApp.h; path = Firebase/Core/Public/FIRApp.h; sourceTree = ""; }; + F6E6EBF71B53225C8F92782A7CC19944 /* StyleableUIElement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StyleableUIElement.swift; path = Sources/UIKit/StyleableUIElement.swift; sourceTree = ""; }; + F6EDB24AD1F08BD38D4E0B70CC036804 /* ru.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ru.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj"; sourceTree = ""; }; + F7515C947EF6212592653822C53CC690 /* FIRInstanceIDCheckinPreferences.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinPreferences.m; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m; sourceTree = ""; }; + F7535A4C380C47E118395A613AF3D849 /* BonMot-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BonMot-umbrella.h"; sourceTree = ""; }; + F7696B90A3B3D1C34C7E852254DD74F1 /* Swiftilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Swiftilities.framework; path = Swiftilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F95AA7ACDE907999406636AE9140BF79 /* AdaptiveStyleTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptiveStyleTransformation.swift; path = Sources/UIKit/AdaptiveStyleTransformation.swift; sourceTree = ""; }; + FA50610602A727B99D7294CFF81CC8E8 /* Pods-Services.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.sprint.xcconfig"; sourceTree = ""; }; + FA555490178D1D5AE635B8B28338E254 /* Swiftilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Swiftilities-prefix.pch"; sourceTree = ""; }; + FB1B0B49E7137AD9BBD29842C2A3A7BD /* FIRMessagingCodedInputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingCodedInputStream.h; path = Firebase/Messaging/FIRMessagingCodedInputStream.h; sourceTree = ""; }; + FB31D468DB67CC3C68E932FF60724283 /* NSURLRequest+HTTPBodyTesting.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSURLRequest+HTTPBodyTesting.m"; path = "OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.m"; sourceTree = ""; }; + FB7E0D532911BBB43E2A8AF72818A0DD /* FIRMessagingDataMessageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingDataMessageManager.h; path = Firebase/Messaging/FIRMessagingDataMessageManager.h; sourceTree = ""; }; + FB9EDEE9036C9154BDA9F866724100D7 /* Firebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Firebase.h; path = CoreOnly/Sources/Firebase.h; sourceTree = ""; }; + FCBFF9345F652100273AE93760F66435 /* Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig"; sourceTree = ""; }; + FCCFBDA197465FE364E665276C2A88CA /* FirebaseInstanceID.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstanceID.modulemap; sourceTree = ""; }; + FCD38CBF4748B96190468E88F12A2064 /* Shapes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Shapes.swift; path = Pod/Classes/Shapes/Shapes.swift; sourceTree = ""; }; + FD58305059DB6EF784EF634B198DD3CB /* FIRInstanceIDTokenFetchOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenFetchOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m; sourceTree = ""; }; + FD757FD2EC6B3B19A20C755C1B166C5C /* Anchorage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Anchorage.modulemap; sourceTree = ""; }; + FDC9DBDC4B19FB33CDC14DE23114B21C /* FIRMMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMMessageCode.h; path = Firebase/Messaging/FIRMMessageCode.h; sourceTree = ""; }; + FF40060DC0344F915D924D3DC88F272D /* CGFloat+DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CGFloat+DeviceSize.swift"; path = "Pod/Classes/DeviceSize/CGFloat+DeviceSize.swift"; sourceTree = ""; }; + FF710E85F020077130E558211B5B8D8A /* FIRDependency.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDependency.m; path = Firebase/Core/FIRDependency.m; sourceTree = ""; }; + FF86C6514C399C0918A89B10C69289BA /* AcknowledgementViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementViewController.swift; path = Pod/Classes/Acknowledgements/AcknowledgementViewController.swift; sourceTree = ""; }; + FFC35B00BCB6D00D5DC095E60BA6F8D5 /* DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeviceSize.swift; path = Pod/Classes/DeviceSize/DeviceSize.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 1003DD60B3818FC0B39B8E5E64264D0B /* Frameworks */ = { + 07E3F9AF597FEC90D3D85283E3E5DA0A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A29D8AA89F0BF6B0871D213341DFC369 /* CFNetwork.framework in Frameworks */, - 51AEC9EDBD8252C6ECEC8264217060CF /* Foundation.framework in Frameworks */, + 9D86C6E7427763F4CC75403A37ECB547 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 1B956845D52108B118A34850891255F4 /* Frameworks */ = { + 0D430FA595C12BF6C51B1E5D7DA62489 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A9F139BA8F48DB38532AAD38F6D5C669 /* CoreData.framework in Frameworks */, - A97F384287EC736D01335030A60536E8 /* Foundation.framework in Frameworks */, - C2FE21AE758AA4C15321D3C5597F4B99 /* MessageUI.framework in Frameworks */, - EF310CF64A4AB66DE85A0573C718E220 /* UIKit.framework in Frameworks */, + E237EA812A181AA46ABC963AC29854A5 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 36A98C2CBB2DD03C3AF6D0161881C871 /* Frameworks */ = { + 1EAA3BD0F5BEEE46CCBAA84201853CB8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 90739588523B5D65BC6CE9E4B0B1AC71 /* Foundation.framework in Frameworks */, + D05E35FCFD0AD588208B9A3258ED8F9C /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 512E07F8CBBE765203C2234921A15779 /* Frameworks */ = { + 255C7B5ED5FE9184B51E5BED246FA3DD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D898348F4D8F2912DE123B843405205D /* Foundation.framework in Frameworks */, + 7E9687A54B05381DCB9BAAEA72366EA7 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 520EE3055734BB8016B7C66C499D04AA /* Frameworks */ = { + 28D36CD0B6FFBB03EEF67B156AEE1B4C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D2813D340E46C0B4343AE0B994514703 /* Foundation.framework in Frameworks */, - BD86B2C7553D3D4C26777144D81B0906 /* UIKit.framework in Frameworks */, + 6B02408E859D41775E7C99C72211E233 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 62549CEBDEDF5CCF226A2CCD9E564BF6 /* Frameworks */ = { + 32D9EDE9ED3871400CB94EF9184C0D6D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CB13CCC62B5572D173A5F3759E4F23BA /* Foundation.framework in Frameworks */, + 04EF7CA88D2E1D49B56D74409399559A /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 70F937D133B19D54060419760D04248B /* Frameworks */ = { + 3ABCC0FD127A6AC59FE23898248C80CF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 061A426D3F457E6D0A052767C3F95076 /* Foundation.framework in Frameworks */, + B26BD92ADC60A9F477AF155252F41C61 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7594253E7AE8385881D06D1D8D1C2F60 /* Frameworks */ = { + 4071E424BB335DEAE15B6918D860D684 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E46129D5E43637E7B0711552796A944C /* Foundation.framework in Frameworks */, + 45E7C2C769D51937061338A69BEE2316 /* Foundation.framework in Frameworks */, + CDE4C38B065973A40B8B7C844D236F86 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8DC95DB7322A102F9E7759CA809F36CE /* Frameworks */ = { + 726B5C2231D21F110E448BFD5292F6A1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 67C20222D613F76731013C8B7C0A3CF8 /* Foundation.framework in Frameworks */, + A85388EF392B19C59DC3C5F54AE550BB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - D8A62289535A21591BCB588314E6C871 /* Frameworks */ = { + 74C2CDA0B2C1E3C0ACC15492B3B38619 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - FA16B3A8C9B5B395CC6DF41609CA4D6C /* Foundation.framework in Frameworks */, + 2723FECBFB4E4EE1EC645516FBB232D4 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 03FF892223A1929709776BF7189E75D9 /* FormattedTextField */ = { - isa = PBXGroup; - children = ( - D90A96D40B7CB86171BF8078F9CA3D9A /* FormattedTextField.swift */, + 96338CCDB13BC8D010311E35BC765F14 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F58012B0BEE8E73287F2A68FEDAD92B2 /* Foundation.framework in Frameworks */, ); - name = FormattedTextField; - sourceTree = ""; + runOnlyForDeploymentPostprocessing = 0; + }; + A2696FAB0EC2BE55C4464984FF5957B7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D80417305501039BA0BDDB62948E193 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9CBED312356F3CEFCFBBCD19C51292D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BAB7813CCBF7A137B84D0EAFC620B6DA /* CoreData.framework in Frameworks */, + 0F8CD4F146F1C58231026AAF09FAC5EE /* Foundation.framework in Frameworks */, + F387A6A0B4F0712AB31A31AF06E1437D /* MessageUI.framework in Frameworks */, + 1C3586AF524004892635EFD9A2F411EC /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AAEE8989AA8CAA1C579BE02343C9D362 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1077DE8C92C90C40F4D8ECE47B48EDB8 /* Foundation.framework in Frameworks */, + 7EEA98DF6EA7BC488FC2C7DC4579BD86 /* Security.framework in Frameworks */, + 148F3B7A2FF4E9CAC78C9E5AB0286CBB /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B18D41FB07D1B0D40F34100516637DCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CAE0EBE0C0215C8BD9ACB0BD0562526F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C5AF32A927179B590C49D6A14BF9158E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F833EC5D09A5161EE957E89F80A80BC7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DEB02DD77A9565F861100EC194EA6E99 /* CFNetwork.framework in Frameworks */, + 9FBAB5AB3AFE3F48C77BAD0033828124 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; }; - 0621EC7551BC056E7A033F9FADDD109D /* Frameworks */ = { +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 008F18918E7698B497FF8188729031AD /* Sourcery */ = { isa = PBXGroup; children = ( - E6CDD1E32FFC400D46C2622FA77E0AA1 /* libGoogleAnalytics.a */, + 788A2F1337113677CD6B6F0562BEACE1 /* Support Files */, ); - name = Frameworks; + name = Sourcery; + path = Sourcery; sourceTree = ""; }; - 06A3B21646FB5ECD335CB48557ACF6BE /* Frameworks */ = { + 008F623D5F4F4DAC4CE6F23C456144BD /* iOS */ = { isa = PBXGroup; children = ( - 62A0F259EB5E8BF8A9D802020E3C6C2D /* Crashlytics.framework */, + 6010A7276EC10495D966DCFE5E3C113E /* CFNetwork.framework */, + 8A467A3E9E3137B15241AA445AAA69D3 /* CoreData.framework */, + 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */, + 2FA78D05699B3A7B758DCA452BE2C72E /* MessageUI.framework */, + 2207F5B391C14F1738C82A01AFB21DD1 /* Security.framework */, + CCE4EFC833EB090ACE8EAA95D8F1FB5D /* SystemConfiguration.framework */, + 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */, ); - name = Frameworks; + name = iOS; sourceTree = ""; }; - 0A3AD2032D53BB89BD7F0CF156B13F29 /* Compatibility */ = { + 009380C89EA1FF9D5353746EAEF1EEED /* Crashlytics */ = { isa = PBXGroup; children = ( - 0CA525AAB4893235D02EA212CA8407AE /* Compatibility.swift */, + E32BE18C7E79232857089AE39A09A626 /* ANSCompatibility.h */, + 5674AE212A0219BB0B7D3C5798B9D7E6 /* Answers.h */, + 7DF716A590C33DA0E5141543D157C552 /* CLSAttributes.h */, + AD4B1920B3B7BA2136B85A1738A0948B /* CLSLogging.h */, + 6CF234F15578D78CE0B9F963AE67AD0A /* CLSReport.h */, + D3761200331DF867B994EFC4B6F238B8 /* CLSStackFrame.h */, + 31ADA9CE18EE4DD7B2A1D3B81C8C8B97 /* Crashlytics.h */, + 972401FA47F7EB697BFBC5DE4DAA0651 /* Frameworks */, + 658C4AB79E2F1A8A07EAE776B3CC23B7 /* Support Files */, ); - name = Compatibility; + name = Crashlytics; + path = Crashlytics; sourceTree = ""; }; - 0A5BB9608F12CCDF4297C355037B6706 /* Pods-PRODUCTNAME-PRODUCTNAMETests */ = { + 02309E965B34DCCD4D31C8903492D26F /* Support Files */ = { isa = PBXGroup; children = ( - 467A292772A289D715C80B2C2CB65115 /* Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap */, - D7092F8161B004CC1F80E7A6C21E1782 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown */, - E17CAFC73159C1C1EB2C35ECFFDCF234 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist */, - 2FB8C1752861586CF1E04E22B05009B9 /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m */, - 474A11822039E6AA6B471CD830ADD05F /* Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh */, - 60E972D817C96D8EEFF0C1423650DDFD /* Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist */, - 6F23572C7CB158962AEB29506087D42A /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h */, - 3FA96E21CB7C709D604705CC1A70427A /* Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig */, - DA0914676ACB3881C960293BB680AECD /* Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig */, - 76CC1EB38705E8C45784419E12627B8B /* Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig */, - 29EF59452D21EA57CF6157AFAE72F043 /* Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig */, + 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */, ); - name = "Pods-PRODUCTNAME-PRODUCTNAMETests"; - path = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests"; + name = "Support Files"; + path = "../Target Support Files/SwiftLint"; sourceTree = ""; }; - 0CF4592BE7C00EC061DDC98F28B45103 /* Alamofire */ = { + 02616AE4D5C78B93D9285050DF9BB523 /* Acknowledgements */ = { isa = PBXGroup; children = ( - C42BE2BD8793574C8CCFF047DE230880 /* AFError.swift */, - 673ABFE194DF7A08FA263E12BAB82F4C /* Alamofire.swift */, - B7268C56B15EE03AC9317CFB3648AE37 /* DispatchQueue+Alamofire.swift */, - 7B61F355D3DB41F42478FC6C1F38A450 /* MultipartFormData.swift */, - E6F2B0D3C4AE001AA8D39C968195273A /* NetworkReachabilityManager.swift */, - 67CEC4C18F7EF40BF8EF7C4EA61392DB /* Notifications.swift */, - FD0003595E56E3351A484C39D062FAA5 /* ParameterEncoding.swift */, - AAAAC152788B64C89E923A18277EBA4C /* Request.swift */, - 6F7BCF16E3577A7314986934680E4C23 /* Response.swift */, - 39279866EC1760AFEE29D2DEEED6C856 /* ResponseSerialization.swift */, - 412B8AA2EB07D89E85469CB8B5773CC3 /* Result.swift */, - 4096AE254E9EB97D97FD6EB20D605B6A /* ServerTrustPolicy.swift */, - BF48041B0643C6B8315D6381008DEE3C /* SessionDelegate.swift */, - 3A3E0BA8DC4603ECFD3151F8B3C81598 /* SessionManager.swift */, - DB96B984A6D557536E37D38A9C71887F /* TaskDelegate.swift */, - 5086A712A691195906CCBD885DAF44FB /* Timeline.swift */, - 2448D385AC85F37AF99BFC03ACAAB403 /* Validation.swift */, - F59A8AD80AFFA490B6A45C134478C1C1 /* Support Files */, + 91A527A11C0F5C0E19DEF21E7B9C7F7E /* AcknowledgementsListViewController.swift */, + 3D6419DC93CAC1E865DD9A730B5C8623 /* AcknowledgementsListViewModel.swift */, + FF86C6514C399C0918A89B10C69289BA /* AcknowledgementViewController.swift */, ); - name = Alamofire; - path = Alamofire; + name = Acknowledgements; sourceTree = ""; }; - 10940FBD6FB6D853861B1B2B407921CA /* ImageHelpers */ = { + 0399B942A602E396575791AC8C00C305 /* Support Files */ = { isa = PBXGroup; children = ( - 3E41B0F9E8C162A676783159D2E6BB11 /* UIImage+Tinting.swift */, + BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */, ); - name = ImageHelpers; + name = "Support Files"; + path = "../Target Support Files/SwiftGen"; + sourceTree = ""; + }; + 03C52F83D51E179A4C50733DEECC309F /* FirebaseAnalyticsInterop */ = { + isa = PBXGroup; + children = ( + 511A6AAEF7B2FA3135202FCC07BF3E65 /* FIRAnalyticsInterop.h */, + E02A8313137BB858673B63F616E21827 /* FIRAnalyticsInteropListener.h */, + E27982EA462CEA4BDA8EC7253E091FB9 /* FIRInteropEventNames.h */, + CFF7EEAD7E8E9673C73848326928A6CA /* FIRInteropParameterNames.h */, + 4E81DF758C7837257EC6D514FD5F7CF6 /* Support Files */, + ); + name = FirebaseAnalyticsInterop; + path = FirebaseAnalyticsInterop; sourceTree = ""; }; - 120CF486BAFD376244CEE1879E7EBC96 /* Lifecycle */ = { + 05B1CA5F6FC7AE0E1EC3D2B58262045F /* KeychainAccess */ = { isa = PBXGroup; children = ( - 8E55C6090DEF8FF17C4877AB940FD591 /* DefaultBehaviors.swift */, - 18A0C90ABF64C64D2F8388FD400A65C3 /* LifecycleBehaviorViewController.swift */, - 276D6C93C6813A9140365BF3CBD94A65 /* NavBarHairlineFadeBehavior.swift */, - 3639D14F3C07D749FB3063E068487445 /* NavTitleTransitionBehavior.swift */, - 7B0FA4328DAC940D1CB38E6FBC0DCDD6 /* UIViewController+Lifecycle.swift */, - C56086F41BE1C76C0A2162242BE882BB /* ViewControllerLifecycleBehavior.swift */, + 7D3E35ACC5108C1B4DEF24DD53900541 /* Keychain.swift */, + 4C3E423F1295AD2DB253BFC225128A1B /* Support Files */, ); - name = Lifecycle; + name = KeychainAccess; + path = KeychainAccess; sourceTree = ""; }; - 210F5A43F4BA6465B481576669D7661E /* Core */ = { + 0DA3027D10365E88FAE40797BBE0183B /* Deselection */ = { isa = PBXGroup; children = ( - AD5BD87CBD27D13BE3B64470D2514F3E /* Compatibility.h */, - 8616019682F89AF777F1467F9FADF221 /* OHHTTPStubs.h */, - 1FA9640C042660F51CFBC1B9D754150A /* OHHTTPStubs.m */, - A71071A87AEBBA036F448F39A4AF7226 /* OHHTTPStubsResponse.h */, - AD4EA92B56734A8CA71BFB65EC5996C7 /* OHHTTPStubsResponse.m */, + EEB3012499F8855E88664D9000D9DCE4 /* UIViewController+Deselection.swift */, ); - name = Core; + name = Deselection; sourceTree = ""; }; - 24661EC968A27C8194E87D8F4C8DFEDA /* Support Files */ = { + 1107F56DAC35E1270FAD72DE01F6E7C2 /* Support Files */ = { isa = PBXGroup; children = ( - 7111D87220CD12D9B160A6B7879E1A7A /* SimulatorStatusMagic.modulemap */, - 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */, - 9A1965AF062F89C7BDA3AE35620B5182 /* SimulatorStatusMagic-dummy.m */, - 5E43976F0F6BEFD1D8B1A747810E1EB9 /* SimulatorStatusMagic-Info.plist */, - 519CB531B27E0A624D038221B6D26038 /* SimulatorStatusMagic-prefix.pch */, - BC96213BE7B62B82294197DF2AC70DA8 /* SimulatorStatusMagic-umbrella.h */, + B1032898B87F1DAFA71E47C7FCB2E415 /* BonMot.modulemap */, + 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */, + 0055556FD5940D94B5719D2CE306ED83 /* BonMot-dummy.m */, + 15A36FCCB6649BA511408B3F1D946285 /* BonMot-Info.plist */, + 5079F288993DCE2E3F57BD1ECD985F0E /* BonMot-prefix.pch */, + F7535A4C380C47E118395A613AF3D849 /* BonMot-umbrella.h */, ); name = "Support Files"; - path = "../Target Support Files/SimulatorStatusMagic"; + path = "../Target Support Files/BonMot"; sourceTree = ""; }; - 281478A870268B2E3D4118E01D17010B /* Support Files */ = { + 13A10E37013F0F0D3C8A35C9A9D41EA0 /* Compatibility */ = { isa = PBXGroup; children = ( - 2576CF28FDBBF7E2E16AD4DC47FE9EE3 /* Anchorage.modulemap */, - 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */, - 4E340EC5B601C12215D9F8E375C37261 /* Anchorage-dummy.m */, - E649566A94614794DCA667332EDBB277 /* Anchorage-Info.plist */, - 3411EC3BF6C45108122770A9510E4DAF /* Anchorage-prefix.pch */, - B576D87C99AA3051DC9EFE733505C01B /* Anchorage-umbrella.h */, + AFE96786D662F36B014DB2976712E52D /* Compatibility.swift */, ); - name = "Support Files"; - path = "../Target Support Files/Anchorage"; + name = Compatibility; sourceTree = ""; }; - 2C290985CBE0A9B5FAE7C9FE0A6F42A9 /* Support Files */ = { + 13EF57D50F79CFF13C4996257901FDCC /* Environment */ = { isa = PBXGroup; children = ( - 40F8BD0AE7464E998720C28C143621BE /* KeychainAccess.modulemap */, - C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */, - 7E61565DBEC973F19175F0B6B4BF9251 /* KeychainAccess-dummy.m */, - 2E0B0149FAAF2D1D209AED840BEF43CC /* KeychainAccess-Info.plist */, - F91A8173C9C7657C0E2880FF9046516E /* KeychainAccess-prefix.pch */, - A80FB9309074DE8E3648C328313041C2 /* KeychainAccess-umbrella.h */, + 5439C399E40C811A0CC58CD80BF419DB /* GULAppEnvironmentUtil.h */, + C3BE33C9694478A1505C09DAF4276BAA /* GULAppEnvironmentUtil.m */, ); - name = "Support Files"; - path = "../Target Support Files/KeychainAccess"; + name = Environment; sourceTree = ""; }; - 2F509B4DFD1746DF49A4CBE5A55099B6 /* Sourcery */ = { + 1B6124501CF65ED3F6A2AD1A93DBAC2D /* Swiftilities */ = { isa = PBXGroup; children = ( - B77847F620609B954972201E68BBBF34 /* Support Files */, + 8685EDF6DBF9F3844A945C3B5F860AB9 /* AboutView */, + 52411C2325EA0E6639195CA9110A2234 /* AccessibilityHelpers */, + 02616AE4D5C78B93D9285050DF9BB523 /* Acknowledgements */, + AB4E2AFBBBBF559816C14051C59A22D0 /* BetterButton */, + 3A6DE26E8120CFC94EB0439625F7E334 /* ColorHelpers */, + 13A10E37013F0F0D3C8A35C9A9D41EA0 /* Compatibility */, + 5D975087B778CF0E10D511A544EC1BDC /* CoreDataStack */, + 0DA3027D10365E88FAE40797BBE0183B /* Deselection */, + 41BE4ED90D51A0C0F569F368E71DE98B /* DeviceSize */, + BE2E0F88645A73CD5BA9E99C1452EAEE /* FormattedTextField */, + A253B1E80FBA3C2BDD64EBC7F7DA3107 /* Forms */, + 9AC8E57272E0D480F3376E031CF9D360 /* HairlineView */, + 989DC329BA99D7559AF31C340D4FB904 /* ImageHelpers */, + 8FECC04822D33D646019B4479EA366F9 /* Keyboard */, + E09CF835A9CE9B38B033D04BE754B8C6 /* LicenseFormatter */, + C27D89BC0C94CADF409F60D4FB950035 /* Lifecycle */, + F04C2CDACCB32D83923281C298391F52 /* Logging */, + 2502596E810E33BBF0AA7B645BEEBD83 /* Math */, + F207982E6DE213CFE74F9EF7393F63A1 /* RootViewController */, + A0704D01E12AD83ADCAF5B229CE99161 /* Shapes */, + 6D2197C24F0848C862E51C94CF51A420 /* StackViewHelpers */, + A303943FD81E6344A959EF2275877C3B /* Support Files */, + 872C1397FD565D4C0B9EFDBBCED2AAAF /* TableViewHelpers */, + 8B8A98ECF03760402D075F38389B3988 /* TintedButton */, + FC97710BA2AAAA3C677BBC481F15EDAE /* Views */, ); - name = Sourcery; - path = Sourcery; + name = Swiftilities; + path = Swiftilities; sourceTree = ""; }; - 37E1736714D26724253BBD4361E48477 /* LicenseFormatter */ = { + 1C939FBA6FABCCA30B1290EE3ACA9D09 /* Firebase */ = { isa = PBXGroup; children = ( - 70668D84A9B3C780A359D0F2B58A1D4B /* LicenseFormatter.swift */, + 4F0A8C75F385295E95A8A89975B92862 /* CoreOnly */, + 525AB3E395182778A970F9C5207657AD /* Support Files */, ); - name = LicenseFormatter; + name = Firebase; + path = Firebase; sourceTree = ""; }; - 3BC2338E51558CD35DBAD43E4CE594C3 /* OHPathHelpers */ = { + 1CA59AED19FCBF816340C45A5F720DFF /* OHHTTPStubs */ = { isa = PBXGroup; children = ( - BEED7AEAC6B377BEABA32BCA6E029D06 /* OHPathHelpers.h */, - 2C90242292A7BE097ED8F53F6314A670 /* OHPathHelpers.m */, + 2C08EFBA82D103166090522B94C4FE5D /* Core */, + 3246FB6EFFC4F5883B7C267801F2F1D1 /* JSON */, + B7C8A5E2542B08353007D5D146E3951A /* NSURLSession */, + 9F3FB97F3B837239BF3776F5642D3884 /* OHPathHelpers */, + 4FA174D92C9CCB6E07FD3C9C66C9F781 /* Support Files */, + B51FA2DAB550422A08450335F068110D /* Swift */, ); - name = OHPathHelpers; + name = OHHTTPStubs; + path = OHHTTPStubs; + sourceTree = ""; + }; + 22012F4F0899CC6365FA911D9C7ADA3E /* MethodSwizzler */ = { + isa = PBXGroup; + children = ( + 6407CC37ECE767179AE4ED00301D5C52 /* GULOriginalIMPConvenienceMacros.h */, + 47EBEF062D1954D670444D5FB49CB050 /* GULSwizzler.h */, + A668229ECF671E377647F4DE649FE2D9 /* GULSwizzler.m */, + ); + name = MethodSwizzler; sourceTree = ""; }; - 3C3C7D9D5069BE48050495089CB0C052 /* Support Files */ = { + 230DD97E2682539EBF5CBB6EFCAB3D1B /* Support Files */ = { isa = PBXGroup; children = ( - FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */, + D9A9C2C923605432B520F3DCE9D1F43C /* nanopb.modulemap */, + 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */, + AD9FCFD914EDA9CDBDE1BA40686E48E0 /* nanopb-dummy.m */, + 5BE4AF9D183DD4AA86ED02D801EC64FA /* nanopb-Info.plist */, + 8750CA9FEFAD9991DCE303273D306351 /* nanopb-prefix.pch */, + 22D8C3460BFD762A935246A9445DDDB6 /* nanopb-umbrella.h */, ); name = "Support Files"; - path = "../Target Support Files/SwiftLint"; + path = "../Target Support Files/nanopb"; sourceTree = ""; }; - 3CB3DA0AFA5A77F95FBA304DFB8BE9E3 /* DeviceSize */ = { + 24067F61C33DB58975E3961238A8DDF5 /* AppDelegateSwizzler */ = { isa = PBXGroup; children = ( - C427306A6F25ED154EDC741171B0672D /* CGFloat+DeviceSize.swift */, - 1D90E1557A97E8534260AE63FB8122C2 /* CGSize+DeviceSize.swift */, - CC6991AC15FB6E796C0D2D216AB1B409 /* DeviceSize.swift */, + 60057B688B56F5C62D15997BB9EDEFDD /* GULAppDelegateSwizzler.h */, + 6DF740D3ACE024C9F6487F0DBFBBC4B7 /* GULAppDelegateSwizzler.m */, + 7F492B106E8EB1E2C72059F4CEC2ADF4 /* GULAppDelegateSwizzler_Private.h */, + 0D8C01D7DC37A7E86CB6EB912842D669 /* GULLoggerCodes.h */, ); - name = DeviceSize; + name = AppDelegateSwizzler; sourceTree = ""; }; - 434B27B3D4D39B0FFE9CC5249CE90B07 /* RootViewController */ = { + 2502596E810E33BBF0AA7B645BEEBD83 /* Math */ = { isa = PBXGroup; children = ( - ACA3A4AF812957B34242F8835CB3ECFB /* UIWindow+RootViewController.swift */, + 526F1F36C6164054C3753D3E4D5C5C6B /* Clamping.swift */, + DEE2591C629B8D1D99F7EB621AFE24BA /* CubicBezier.swift */, + C88DB8688B47BE7D71F76B016AD52DA8 /* CurveProvider.swift */, + C1364213BD031AD3BAD42D9E69571ADD /* FloatingPoint+Scale.swift */, ); - name = RootViewController; + name = Math; sourceTree = ""; }; - 471196AE447819E593C2719250F052F0 /* JSON */ = { + 2516CFCC31378C0E7AD42AB3AEFD5046 /* Support Files */ = { isa = PBXGroup; children = ( - 8322C8C3CC5229674C4860D5DADC299F /* OHHTTPStubsResponse+JSON.h */, - 84B709879A680D555D406FEF46B4B386 /* OHHTTPStubsResponse+JSON.m */, + 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */, + 2DA62A31E606D66A0A8DF99FFB00CB54 /* ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist */, ); - name = JSON; + name = "Support Files"; + path = "../Target Support Files/AppCenter"; sourceTree = ""; }; - 485E8618AF9F5DF813FB9AD3394C9F98 /* Acknowledgements */ = { + 28FF4F61E9D98CE24E3756A1DB302AA4 /* Distribute */ = { isa = PBXGroup; children = ( - 62AF34195393D64764BB5AE60633CF06 /* AcknowledgementsListViewController.swift */, - 60C2A42E80DFA41030FABD4A88393F4D /* AcknowledgementsListViewModel.swift */, - 0EB51FACE363CF08AD66B491366ECCA6 /* AcknowledgementViewController.swift */, + 524CDDEC3E70D2318C9B6BBF8351CCFF /* Frameworks */, + 4EC2D36F6022B2118DC1A8040605C49F /* Resources */, ); - name = Acknowledgements; + name = Distribute; sourceTree = ""; }; - 4C5E989981AF2A86EAE4FC8874303A39 /* OHHTTPStubs */ = { + 2BC40A9034E168E418BAA7541218D456 /* SimulatorStatusMagic */ = { isa = PBXGroup; children = ( - 210F5A43F4BA6465B481576669D7661E /* Core */, - 471196AE447819E593C2719250F052F0 /* JSON */, - 86E9FE5029DF109803765A3AC8DFDF1B /* NSURLSession */, - 3BC2338E51558CD35DBAD43E4CE594C3 /* OHPathHelpers */, - AC01D6C29F288E9B876B6D64EC05ADA8 /* Support Files */, - E03F86A5298A02EDA71AD21D5CC0C456 /* Swift */, + CD626DB394FDD0FF51FD012D20A334F0 /* SDStatusBarManager.h */, + 65DFDCD7CA8EB72916D84A809A50C7FD /* SDStatusBarManager.m */, + ED9E474AFCCD58C67C788DC90A8A9AD0 /* SDStatusBarOverrider.h */, + 76848D31B6A54F9167B3E81B2B157273 /* SDStatusBarOverriderPost10_0.h */, + 94F243E68DA74E3EF1064781840A6375 /* SDStatusBarOverriderPost10_0.m */, + 1997495D70A0AFDD3D4437EFFABE3048 /* SDStatusBarOverriderPost10_3.h */, + 21921F807B4B34CE95F4333954EF9330 /* SDStatusBarOverriderPost10_3.m */, + ECE318A98BEDBC9D92401EFDAE6EAC84 /* SDStatusBarOverriderPost11_0.h */, + AD72DEE352EC54E08A0DDA10EEDB3D49 /* SDStatusBarOverriderPost11_0.m */, + 322AE82498430F3AA39C51C2BC4FB15F /* SDStatusBarOverriderPost12_0.h */, + CC67002EE29757073391E2064F1BD0E6 /* SDStatusBarOverriderPost12_0.m */, + 53F88E4F0E3A11E9B5D721DEEDEB2F09 /* SDStatusBarOverriderPost8_3.h */, + 180977BDD0E3E3ED4CC91DF5BCD29868 /* SDStatusBarOverriderPost8_3.m */, + 13EF5B0944ABC90005395BF63E59D1B9 /* SDStatusBarOverriderPost9_0.h */, + 047E636E2BACE2765A28ADD8F0A0E5CA /* SDStatusBarOverriderPost9_0.m */, + C40BAC08597BADB1064666DF2633CF2D /* SDStatusBarOverriderPost9_3.h */, + AD7C3AE346CDF47C559CAA1E29D38819 /* SDStatusBarOverriderPost9_3.m */, + 1F937168226D3E9CD0FDFCA1B32629DA /* SDStatusBarOverriderPre8_3.h */, + 433FD3F0C39CB9CDDF7F51F624242518 /* SDStatusBarOverriderPre8_3.m */, + 9B39C83358AAA4C9B0BE04FCA31A4DD4 /* Support Files */, ); - name = OHHTTPStubs; - path = OHHTTPStubs; + name = SimulatorStatusMagic; + path = SimulatorStatusMagic; + sourceTree = ""; + }; + 2C08EFBA82D103166090522B94C4FE5D /* Core */ = { + isa = PBXGroup; + children = ( + 4FCB1518EBBFFD314F997C63F2AE720F /* Compatibility.h */, + DB5BD78F6D7A28ACB840F946DCBA826F /* OHHTTPStubs.h */, + 9BE96B90011674F188BAA0598BD91B53 /* OHHTTPStubs.m */, + 5A3F12E1757587C015AB1F285348CFAB /* OHHTTPStubsResponse.h */, + 3C9D78BDFE3971F2EF43F1EE93290481 /* OHHTTPStubsResponse.m */, + ); + name = Core; sourceTree = ""; }; - 4F64DC591F8303AA1CF2D7BC16037F93 /* Support Files */ = { + 2F42D4BF0DDF237686424E3A4EF51E70 /* FirebaseMessaging */ = { isa = PBXGroup; children = ( - 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */, + 9A68AA6C83230BBFED7CC97DA09A987B /* FirebaseMessaging.h */, + 5D6FB40F4F28DA6BC422DDDDBBC7CDA6 /* FirebaseMessaging.h */, + 9C8948FFD9D354F2001C98CEE8B45E08 /* FIRMessaging.h */, + E774767ADA7D8B661ACBB80E499003DD /* FIRMessaging.m */, + 8E5AF5D638A5E46AC1F536B0D9FC686E /* FIRMessaging_Private.h */, + 98DE82806BC35C7A7C3ACBCF0C7B379F /* FIRMessagingAnalytics.h */, + 9AAD5AF881A90E6C8ABB964271CD3D7F /* FIRMessagingAnalytics.m */, + 7930F6E4B1DBA1F8B3A51893DC47D6D9 /* FIRMessagingCheckinService.h */, + 44A66697CB999F1B94BE112FF3F6082E /* FIRMessagingCheckinService.m */, + 2C51C1D95A23094AED0ABE47DE23F077 /* FIRMessagingClient.h */, + 318F5854818D012A621F4EE3E8A310B3 /* FIRMessagingClient.m */, + FB1B0B49E7137AD9BBD29842C2A3A7BD /* FIRMessagingCodedInputStream.h */, + 986EF3488689CACCCB183285A1909D6A /* FIRMessagingCodedInputStream.m */, + 0951EED81BCFA0803E2B141DE332E11D /* FIRMessagingConnection.h */, + AD183A51FD1FF965003291AC5F048C14 /* FIRMessagingConnection.m */, + 360D12ED7F2D4981DBE39DE4FCDC76A3 /* FIRMessagingConstants.h */, + 67E6336A4DE03D2B54BB4E2D5C377405 /* FIRMessagingConstants.m */, + 6B4A56D8EB5978D426BDC59DC1AA5E2C /* FIRMessagingContextManagerService.h */, + 6C651771BDA251122C0517F98DD229C4 /* FIRMessagingContextManagerService.m */, + FB7E0D532911BBB43E2A8AF72818A0DD /* FIRMessagingDataMessageManager.h */, + E735845AC66A0F18361E9CB0A620082A /* FIRMessagingDataMessageManager.m */, + B8E0195AADB4B77EBBA26DCB16A7ADB1 /* FIRMessagingDefines.h */, + B1EEA6318B7652582ADC0248EF0E862A /* FIRMessagingDelayedMessageQueue.h */, + 468332F23F5D358DB2288F3934AEC350 /* FIRMessagingDelayedMessageQueue.m */, + BC07246B7DD7857DA18E71CDAD1E01D4 /* FIRMessagingExtensionHelper.h */, + 6CFEFDB61382511167CBE5BFA016DFF7 /* FIRMessagingExtensionHelper.m */, + 29977CBD0F0F1352A376A22E58D14F56 /* FIRMessagingInternalUtilities.h */, + E2B37DD9690B667E67C7B749014FDAE6 /* FIRMessagingLogger.h */, + 1500A31AAD61B6B55D1541CEC1F8B821 /* FIRMessagingLogger.m */, + 5F9E4B9D5FF21ED1F4AB75BA5BA13598 /* FIRMessagingPacketQueue.h */, + 3BA9EA5998AA76F74EE798C3CBBECA9D /* FIRMessagingPacketQueue.m */, + 662B607559C369907018526CD34E7A82 /* FIRMessagingPendingTopicsList.h */, + B67FA446F6A78388566D90BDD02B2175 /* FIRMessagingPendingTopicsList.m */, + E19C54CB57055FAC1B7EC1A332B36AE1 /* FIRMessagingPersistentSyncMessage.h */, + 356BEB97A3924CA7A9EFA6E39B529298 /* FIRMessagingPersistentSyncMessage.m */, + 7798FFAA50C6E5C495F258D8A51AFCF9 /* FIRMessagingPubSub.h */, + 949C61608ACEFB9BB47A141E428D5CED /* FIRMessagingPubSub.m */, + 849FE1C62D5BADA93D12508A10FFB88A /* FIRMessagingPubSubRegistrar.h */, + ABF027D832F3CFAAE988298C13DB25CF /* FIRMessagingPubSubRegistrar.m */, + B5D090276832D4024D8B3A5568BEA4DE /* FIRMessagingReceiver.h */, + 7750A59221DB77FAF80CF7B06B985ABA /* FIRMessagingReceiver.m */, + 5725B7F7891756CBC38A7C3FFBA0605D /* FIRMessagingRegistrar.h */, + E3AE805A7D220717142177291A6563DD /* FIRMessagingRegistrar.m */, + 7240263E6AB16234AD51BABC7BEDBFD0 /* FIRMessagingRemoteNotificationsProxy.h */, + E689A6FA791FBDA83E75CA835495CE84 /* FIRMessagingRemoteNotificationsProxy.m */, + 846244C0EC47A8A7BE9B1E2506F77C50 /* FIRMessagingRmq2PersistentStore.h */, + 1F13E67C41FD3508A00AC0A6F6CA8A43 /* FIRMessagingRmq2PersistentStore.m */, + 8BCBB2D56D50E44BD77F0169A7F75E7B /* FIRMessagingRmqManager.h */, + 92F4855C80835F853383873CD1CB78B4 /* FIRMessagingRmqManager.m */, + 37E010E6C2F14B116AD0A6E40D547F39 /* FIRMessagingSecureSocket.h */, + 67D20FEE4726CCB26A931435C6F7F8D6 /* FIRMessagingSecureSocket.m */, + B7A5E48BA4D6DE7CABBE36B040019834 /* FIRMessagingSyncMessageManager.h */, + B4625D667AFBD9425C3A79449E05F451 /* FIRMessagingSyncMessageManager.m */, + 88C8386A2D3A8315518D7FC2CF01A15B /* FIRMessagingTopicOperation.h */, + 6D0CAF61CDA366988A208A7B3648AB10 /* FIRMessagingTopicOperation.m */, + 623AE596A3622CB246F0C91BF962A5EA /* FIRMessagingTopicsCommon.h */, + ED75C449FDA4BD587531DFEE93D42918 /* FIRMessagingUtilities.h */, + D7DEB68026091907EB2EBB5D82C47A00 /* FIRMessagingUtilities.m */, + 4707DEF6F61CF955E8D0164566D43983 /* FIRMessagingVersionUtilities.h */, + 3C1809F979F3942E4C48A86D0F20B10B /* FIRMessagingVersionUtilities.m */, + FDC9DBDC4B19FB33CDC14DE23114B21C /* FIRMMessageCode.h */, + 12D36157D372B866FB49CE4288D881E3 /* GtalkCore.pbobjc.h */, + 21518DB69A5249884D47AA1C030D65A1 /* GtalkCore.pbobjc.m */, + D5EB134AFDFBA28F3347C088E94F3AA1 /* GtalkExtensions.pbobjc.h */, + B4C8749E960A855A7C7965EC2BA8218A /* GtalkExtensions.pbobjc.m */, + BE03FBD1AE757BEDE8D7B21466965FD1 /* NSDictionary+FIRMessaging.h */, + BA59223CF8122E668F27A492727DA05A /* NSDictionary+FIRMessaging.m */, + 5F619742AF64CEB785C8717E281D3DA7 /* NSError+FIRMessaging.h */, + 7E51F53C43C26EC84AD204A2DF58797C /* NSError+FIRMessaging.m */, + A2BA946DCE676E2A736992A6D7F61F5D /* Support Files */, + ); + name = FirebaseMessaging; + path = FirebaseMessaging; + sourceTree = ""; + }; + 309669BC4003FB5E733750D429EB9CA5 /* Support Files */ = { + isa = PBXGroup; + children = ( + 9E5694DFDF2C9E53E5A1BB537671493B /* Protobuf.modulemap */, + E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */, + D7500D2B23B7DC69CCA7B61577BEAD0D /* Protobuf-dummy.m */, + 1D68553FA13FBC980DEA48AD8F4FF33C /* Protobuf-Info.plist */, + C05C63DA5EBF6B109936FE6137E41737 /* Protobuf-prefix.pch */, + 8A2450A9AC3AEDEE3814CEC1893EBE3F /* Protobuf-umbrella.h */, ); name = "Support Files"; - path = "../Target Support Files/Fabric"; + path = "../Target Support Files/Protobuf"; sourceTree = ""; }; - 4F93E6BFC4CC76D46B72C7BD14EEAB83 /* Products */ = { + 3246FB6EFFC4F5883B7C267801F2F1D1 /* JSON */ = { isa = PBXGroup; children = ( - 9FDDC29E87B92F93E44BCD9BE2EDED7B /* Alamofire.framework */, - 96822B1CA2B1F1B51992E9BAD9A99F96 /* Anchorage.framework */, - 96E262BA9A1492BA3FDC9E0786CF277A /* BonMot.framework */, - 301105F4D7338338C59D0195933FA755 /* KeychainAccess.framework */, - A946DCC1815CEAD36C91124C6248CA37 /* OHHTTPStubs.framework */, - 5C36B781D279FBC53B84933BBA772A0E /* Pods_PRODUCTNAME.framework */, - F562BB9A7020F3CBCE41AE3A3CB94883 /* Pods_PRODUCTNAME_PRODUCTNAMETests.framework */, - 8F4D0D3C0C97E223CF4BAEE6393105E9 /* Pods_Services.framework */, - 5426B4EA8AB7C69CCFB6311BF4008D2F /* SimulatorStatusMagic.framework */, - 9AEAE841E281C0D30AD94EEF9FC181AE /* Swiftilities.framework */, + 247C04FA03FB22629ED9C337A195F8F6 /* OHHTTPStubsResponse+JSON.h */, + 73047CD3A9D6F102084B6565479FD975 /* OHHTTPStubsResponse+JSON.m */, ); - name = Products; + name = JSON; + sourceTree = ""; + }; + 37EAF90413960A018228B0E598F8F0EA /* Protobuf */ = { + isa = PBXGroup; + children = ( + 22D1FCC1043B4DD3CEA939877906ECD8 /* Any.pbobjc.h */, + 2E5D20BCCFC283EBF43CD654944F92FB /* Any.pbobjc.m */, + C392AFDD980E1C6B8554B9CCE3D4F95A /* Api.pbobjc.h */, + 809A9FA0958DAAB72D85475C1510B28C /* Api.pbobjc.m */, + 5805433E9EE4075EBAE342A288525AD4 /* Duration.pbobjc.h */, + B53967F27884E26D24DE4B390642290C /* Duration.pbobjc.m */, + B3B80947892AFE99F690D90E0E6F7A0C /* Empty.pbobjc.h */, + D7EC6B48A447510995672266B84A0112 /* Empty.pbobjc.m */, + 3B333D83F4602F037A199CE1061A7A79 /* FieldMask.pbobjc.h */, + B7873C854D420CA53D1BD7CE0700ACDC /* FieldMask.pbobjc.m */, + 4A12FC33DD08260C9C378A9C2A227833 /* GPBArray.h */, + ADB4B0347B4897392B2245F4E44D0AC1 /* GPBArray.m */, + D9011FC16F020AA7453970FDC70281F4 /* GPBArray_PackagePrivate.h */, + 670326828280195E95A7805733428555 /* GPBBootstrap.h */, + 4D827CD1FACB9020945F3B62976196F5 /* GPBCodedInputStream.h */, + 536F55571CB5D4E8C4CD313EFFC98897 /* GPBCodedInputStream.m */, + D7E5680FC53E7E9F3D5CDFD636890134 /* GPBCodedInputStream_PackagePrivate.h */, + E6D0C984DDF42A7E6B78C3EAE3C981CB /* GPBCodedOutputStream.h */, + 8942E740881A6372C900E36D68EAF4CB /* GPBCodedOutputStream.m */, + 1064EA2176F4289B3F2DC02849A83825 /* GPBCodedOutputStream_PackagePrivate.h */, + 168D0C5421335ACFB5EBB53C584D8B5D /* GPBDescriptor.h */, + 4B1D3820BB2870B22224C025F97B495A /* GPBDescriptor.m */, + 399A0F9FCF8F163E53341ADFC13A530F /* GPBDescriptor_PackagePrivate.h */, + F33A6CC0B7DD266D5F442790D44ACD25 /* GPBDictionary.h */, + 8A10B633A7F6F7DB8565FCD54B2F6015 /* GPBDictionary.m */, + 0D7113D1B1F68315334A5D6E5C78151A /* GPBDictionary_PackagePrivate.h */, + 780F31022D4CCCEEEF6B0433A8907F93 /* GPBExtensionInternals.h */, + E274690FABF5774F0512B21622B9BAD0 /* GPBExtensionInternals.m */, + 7DF32B5609DBC1BE477D33A94686964D /* GPBExtensionRegistry.h */, + 37D1089A0FB89C55B768CC26C804A7B2 /* GPBExtensionRegistry.m */, + 0B179EF2E474E501FD5650C4ADF83782 /* GPBMessage.h */, + F4E200831632A5DA6FE18A80ED063AA8 /* GPBMessage.m */, + 01FC0E2DFCCF55217572DC39EA5C6163 /* GPBMessage_PackagePrivate.h */, + 789045C4CD88187B1C8B6952AD65877D /* GPBProtocolBuffers.h */, + 6FF4D0CB4786B5D9882E4D069869A3CF /* GPBProtocolBuffers_RuntimeSupport.h */, + BB5DFE1F01AFD7800F073ECA808AD019 /* GPBRootObject.h */, + 8B4A5B8EBEA544128E7C93E89A933ACE /* GPBRootObject.m */, + 9EE85328C2AA2BE65AC5476B9A3A4B9A /* GPBRootObject_PackagePrivate.h */, + D50A2051D90DCC03E026A0A56A46F1E0 /* GPBRuntimeTypes.h */, + 58BC5AB95FAF621615835A4436B69D8C /* GPBUnknownField.h */, + E82C57A8834CD3A374E5E52A9DEBA80E /* GPBUnknownField.m */, + 2DF285A229D15CB8F3DFBB3DD3DC7884 /* GPBUnknownField_PackagePrivate.h */, + B7B04D349B7F6EF4AB5D84952D2A53DE /* GPBUnknownFieldSet.h */, + B2127ADF7134D22A7B41243F58B119B2 /* GPBUnknownFieldSet.m */, + 7BE9D1869AAADCD42062E01D5D3C87C8 /* GPBUnknownFieldSet_PackagePrivate.h */, + 7C5A26153063FDC9CF29CACEBFDCE19B /* GPBUtilities.h */, + C4060169D4E6873CF1EEF2A457AC3BD6 /* GPBUtilities.m */, + 8466929A49CE3221978EB36183FD35BA /* GPBUtilities_PackagePrivate.h */, + 20D53BC1D9D046786E39FFC97B7B43A7 /* GPBWellKnownTypes.h */, + 258251CAB54F309E8E640653850C4B32 /* GPBWellKnownTypes.m */, + 053874D026363AC0A03A09A01558AD61 /* GPBWireFormat.h */, + 814B71C2E085A900096EC6AECF6B4CE3 /* GPBWireFormat.m */, + 5BD0138F17C5CEC5217CDE58354221B3 /* SourceContext.pbobjc.h */, + C0865174F215EE5541472B794F16EABD /* SourceContext.pbobjc.m */, + 7A62C867EDE3F5810D57F99ED04E9BA0 /* Struct.pbobjc.h */, + 7D5ABA89BFABB034F15503FA4EA2C665 /* Struct.pbobjc.m */, + 2FDE57075083813209769DB1ECBA097C /* Timestamp.pbobjc.h */, + 9D75377169BF1143EF206F74484FC1F0 /* Timestamp.pbobjc.m */, + 05E39D129D919E418F8D526AC9591021 /* Type.pbobjc.h */, + 1F6EBA7C6997FF0B01735341A694592F /* Type.pbobjc.m */, + 4DE6952B80D386C75EA01A7B003A923F /* Wrappers.pbobjc.h */, + 38337959621A4D9065BD17ACB25371AD /* Wrappers.pbobjc.m */, + 309669BC4003FB5E733750D429EB9CA5 /* Support Files */, + ); + name = Protobuf; + path = Protobuf; sourceTree = ""; }; - 52D0F86B31D357565D421D4C5DC1BB3C /* CoreDataStack */ = { + 3A6DE26E8120CFC94EB0439625F7E334 /* ColorHelpers */ = { isa = PBXGroup; children = ( - BC68423B5D03B01844BE44E57D3105DF /* CoreDataStack.swift */, + E036B66F0200BB21E6A3C50B4A98D7C8 /* UIColor+Helpers.swift */, ); - name = CoreDataStack; + name = ColorHelpers; sourceTree = ""; }; - 5423402C475D3886640C53E07B0412B2 /* Support Files */ = { + 3B2DC82F6FC98950B2D602286A0BA4DA /* UserDefaults */ = { isa = PBXGroup; children = ( - A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */, + 807724545CC9FBB3B33672198DD057ED /* GULUserDefaults.h */, + 36624989E8CA8F0B22557AD8E3ACAEEF /* GULUserDefaults.m */, ); - name = "Support Files"; - path = "../Target Support Files/GoogleAnalytics"; + name = UserDefaults; sourceTree = ""; }; - 55A4C5822968D07AACCB2DE35D1D4A4C /* Targets Support Files */ = { + 41BE4ED90D51A0C0F569F368E71DE98B /* DeviceSize */ = { isa = PBXGroup; children = ( - 98F6046110197DC3661BBBA12005FD56 /* Pods-PRODUCTNAME */, - 0A5BB9608F12CCDF4297C355037B6706 /* Pods-PRODUCTNAME-PRODUCTNAMETests */, - 7F9C09CAAED759953131AA6A0B723C4B /* Pods-Services */, + FF40060DC0344F915D924D3DC88F272D /* CGFloat+DeviceSize.swift */, + E2FDAAF328CFC1916BD31D012F33FA11 /* CGSize+DeviceSize.swift */, + FFC35B00BCB6D00D5DC095E60BA6F8D5 /* DeviceSize.swift */, ); - name = "Targets Support Files"; + name = DeviceSize; sourceTree = ""; }; - 5E3C3393E847FDA37FAEBF7E00DDE1F4 /* Support Files */ = { + 4B759243E3FC5DFD9399CEDDF79EB5AD /* Support Files */ = { isa = PBXGroup; children = ( - 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */, + 7F9F3C7A180A25601F10CA6EDA5435A1 /* Alamofire.modulemap */, + B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */, + 01CDC0351ED7CEC107FB8A77489F99CE /* Alamofire-dummy.m */, + 35BA4A04ECE9B5B06B1021FB70BBB8E9 /* Alamofire-Info.plist */, + D4DEEAB8E3E3054E7C33B89FFE01EF18 /* Alamofire-prefix.pch */, + 55D73A9343E88A26AE65A4223D8C07DF /* Alamofire-umbrella.h */, ); name = "Support Files"; - path = "../Target Support Files/Instabug"; + path = "../Target Support Files/Alamofire"; sourceTree = ""; }; - 6BE7F2180A18F22C70A19933BCED7310 /* Crashlytics */ = { + 4C3E423F1295AD2DB253BFC225128A1B /* Support Files */ = { isa = PBXGroup; children = ( - 111EE320E7BC5B51DA0B08B5F6CCCAE2 /* ANSCompatibility.h */, - 693EB792331AD6ABD61A27768244D086 /* Answers.h */, - F3B6C1F52D3C489842038C172FF057F2 /* CLSAttributes.h */, - DCB901DB5CF0F009F87153156EFD3FAB /* CLSLogging.h */, - CFDD87526BDBCFE4DDF38D11B28728D8 /* CLSReport.h */, - DFD8BF8FFA442A208B702F283FFCD45E /* CLSStackFrame.h */, - 163CBECB08FD3C96E47CB9147E7FB3EB /* Crashlytics.h */, - 06A3B21646FB5ECD335CB48557ACF6BE /* Frameworks */, - 89B5E2C0C1CA80E3D1A21B0866F1BE8D /* Support Files */, + 784571D4952D4EA67F2018794826B771 /* KeychainAccess.modulemap */, + EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */, + F140B1E39A706719A3E80EF3EE95186D /* KeychainAccess-dummy.m */, + 444803A0ADD399B49C628CFC2947F5D0 /* KeychainAccess-Info.plist */, + ADD85DBCA961517182D229A520E707A7 /* KeychainAccess-prefix.pch */, + 9EF45F089BAE93FE828CD9688AA8CA8A /* KeychainAccess-umbrella.h */, ); - name = Crashlytics; - path = Crashlytics; + name = "Support Files"; + path = "../Target Support Files/KeychainAccess"; + sourceTree = ""; + }; + 4C4557B4DD2C0EF6C0E4D60D96ADD8C3 /* Network */ = { + isa = PBXGroup; + children = ( + D8D631A479FBF2CC1551FFD90D0D6CCF /* GULMutableDictionary.h */, + 3B5E83DF94AA1871CCE123E6D44F0B70 /* GULMutableDictionary.m */, + 71D265F83D526F8D4CBAF591F57A1C35 /* GULNetwork.h */, + DC604E06843C199B7238C7ECCDD65231 /* GULNetwork.m */, + 9221AE50CB51C7E8CD93A956CC3EA7C2 /* GULNetworkConstants.h */, + 3E381DBDE829EC743F4F0A730A0EA4E5 /* GULNetworkConstants.m */, + E7BDF86CE64C4E407EBF8A73A20C6EF3 /* GULNetworkLoggerProtocol.h */, + 35D0212C3DBD3EB9B48F92FE6E705124 /* GULNetworkMessageCode.h */, + 8239448521ADE6944ED02A4E4E8F83C5 /* GULNetworkURLSession.h */, + F6B71CAF2E55E96D2C79702EA17AC62E /* GULNetworkURLSession.m */, + ); + name = Network; sourceTree = ""; }; - 6D002A39BF8CFC58BD0D07E789AD8401 /* BonMot */ = { + 4E81DF758C7837257EC6D514FD5F7CF6 /* Support Files */ = { isa = PBXGroup; children = ( - DE0E7C617CC610A75A05A76F56C75DB0 /* AccessibilityHeadingLevel.swift */, - 13DDEF6C866280C73475A52AC509488F /* AdaptableTextContainer.swift */, - DC14BE78C6ADC4A456ED440DA669B424 /* AdaptiveStyle.swift */, - 53A72D85B745ED549CABA1B2596D6E07 /* AdaptiveStyleTransformation.swift */, - 704ACC5578BE8DC6950CC29EA7C1AFE1 /* AttributedStringTransformation.swift */, - 9CA678F606DD3E9ABC1DBDF7400C03B2 /* Compatibility.swift */, - 095ABB58DBD99D3A10453F530368A5F0 /* Composable.swift */, - 08B38982F150A6862B8AD2A945D9B407 /* ContextualAlternates.swift */, - 24EBA9AD10434F4F0FA3C89E27567DDA /* EmbeddedTransformation.swift */, - 89450B8529A81C5B1E75A786D5FABC3D /* Emphasis.swift */, - 5F12A1D968B46216AE4EE506629B554E /* FontFeatures.swift */, - 11D7CFFD8553B55C3A3B2272283373A6 /* FontInspector.swift */, - 08FEAA71D51B643545C21B77DC4D28DD /* Image+Tinting.swift */, - 90AC5B33AAA6EF1AB9164725FFA0B6C3 /* Ligatures.swift */, - 89E43AF1CEC2C19E8EB86AE3397389EA /* MutableCopying.swift */, - 62FABFF9927EB4903E6F34356FF106F4 /* NamedStyles.swift */, - DF1BC0A1B0C287F0903058BAEC132BEA /* NSAttributedString+Adaptive.swift */, - 85A6A4A85CADB17311A03BB6003CDC8B /* NSAttributedString+BonMot.swift */, - C8A1F76AAB60389D3C093AC1A50BF0A9 /* Platform.swift */, - 1CCAE7D4A6245F5F4C44F739DBC1DE61 /* Special.swift */, - 24E6EDD19D24D9E3522A79BF5F36D8F2 /* StringStyle.swift */, - 712AA0B3114BE06914AA73650935B4B3 /* StringStyle+Part.swift */, - 362EF0199AD907539D86EBEF1DE6556C /* StyleableUIElement.swift */, - 863B364319BA1C8E81DB7F006A9A31BC /* StylisticAlternates.swift */, - 45DE58670D5CC4C511D327BD0944AA59 /* Tab.swift */, - 0AD288A8A84E421BED98CFA78BA83CAD /* Tab+Adaptive.swift */, - 04FA80AC5B62CDAB5253E08409C0D0B9 /* TextAlignmentConstraint.swift */, - CDE8ACA571ED75517D0E41EB2D0AE086 /* Tracking.swift */, - 330CCA593DDAE935D8E8573A0728E931 /* Tracking+Adaptive.swift */, - 88E5F6A803FEFEF70F140D44D4DD1CA0 /* Transform.swift */, - D80B127AD7C7BB100CC551B493D3D794 /* UIKit+AdaptableTextContainerSupport.swift */, - D9CA18D0EBAA000A7E08DB708924C2B9 /* UIKit+Helpers.swift */, - 5922604290D09B15C428A4127852F8D2 /* XMLBuilder.swift */, - D41B1FB075B7B8972717CC6236282BF8 /* Support Files */, + 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */, ); - name = BonMot; - path = BonMot; + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalyticsInterop"; + sourceTree = ""; + }; + 4EC2D36F6022B2118DC1A8040605C49F /* Resources */ = { + isa = PBXGroup; + children = ( + 74BE747D93A2FF0D9596DFEB89B88506 /* cs.lproj */, + C8268059830026F500EAD6383BB19F88 /* de.lproj */, + DFDA0DE503139F615A5FB983A7BAFD1A /* en.lproj */, + 9917CC431DC36BB3D118B1AA7A204319 /* es.lproj */, + 829D6EBA77079A9CFF95E76253E1B175 /* fr.lproj */, + B7AD2BE9A6C9E2298E7917BF8FD6E425 /* it.lproj */, + 0F5EF93A5BE453909C31B9C6554C95CD /* ja.lproj */, + 1683A78B7B9007625AE95AAE42A96663 /* ko.lproj */, + 842142B2B14A0BA4AFCC17CBAC0F7C98 /* pl.lproj */, + 0172526E6D3CEFD172AD72474B7F1B03 /* pt.lproj */, + F6EDB24AD1F08BD38D4E0B70CC036804 /* ru.lproj */, + AB8C0F48EBA2E62C0D0D696427AAF734 /* tr.lproj */, + 9217346EC5CA9E35B7D5CC7A1AC82A9B /* zh-Hans.lproj */, + B732E75D7C970C6F08CDE5C6AFDF8702 /* zh-Hant.lproj */, + ); + name = Resources; sourceTree = ""; }; - 6E76B52DFE8B416AC422A204899827B0 /* AboutView */ = { + 4F0A8C75F385295E95A8A89975B92862 /* CoreOnly */ = { isa = PBXGroup; children = ( - 54C8E02EC8ABE5CF2CA2B3840F75FC8F /* AboutView.swift */, - B921E0CBB6CCB74325890A14EE6C3F5B /* AppInfo.swift */, - 9E5B2FEF0A506CDAE2D10761BE2F376E /* FeedbackPresenter.swift */, + FB9EDEE9036C9154BDA9F866724100D7 /* Firebase.h */, ); - name = AboutView; + name = CoreOnly; sourceTree = ""; }; - 715EFDE146C70BF40DC2D065C60FB4AF /* Math */ = { + 4FA174D92C9CCB6E07FD3C9C66C9F781 /* Support Files */ = { isa = PBXGroup; children = ( - 694AD7393AED493BB49E808D261B32A7 /* Clamping.swift */, - 8B9CD9D4507F0BB5DA2B05A298D3C3AC /* CubicBezier.swift */, - 3749D57AF44719F99E7573D0EF50F406 /* CurveProvider.swift */, - 96B35764F050EDE7B00132EF81A34F42 /* FloatingPoint+Scale.swift */, + CDE72026FE9260A75C5737785EC261F2 /* OHHTTPStubs.modulemap */, + 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */, + B7A403AA64C0558925444F207EEADE76 /* OHHTTPStubs-dummy.m */, + F5C73B87D6F5DBC36EAF4F5A2C11C0D8 /* OHHTTPStubs-Info.plist */, + 741B01C4F4159696D4237F6F4D3A98BB /* OHHTTPStubs-prefix.pch */, + 2F6F1BBF9B142B5EF49F87D2D044E829 /* OHHTTPStubs-umbrella.h */, ); - name = Math; + name = "Support Files"; + path = "../Target Support Files/OHHTTPStubs"; sourceTree = ""; }; - 719130B020D019BAB5B597C067CBB10D /* Views */ = { + 51A6420B90C1B77281AFA830BC68F078 /* BonMot */ = { isa = PBXGroup; children = ( - 80930814506B3CE5606AA7DED6CBA9B4 /* GradientView.swift */, - 54CC3A9A9520AF155108F8CE284EB864 /* PlaceholderTextView.swift */, - 72B5BB3EED5E5C863F41621DD901083C /* Protocols.swift */, - FB6C041C62D7A0FC5904F4CA72030FC3 /* TailoredSwiftTextView.swift */, - FBF2880E3762207FCA439FC5B3BFE9D1 /* UITextView+Extensions.swift */, + EC9B9847934B602C43CAC9AE7E2EBD36 /* AccessibilityHeadingLevel.swift */, + AF9BA9F1FCE9E687C9236562D28FBBF6 /* AdaptableTextContainer.swift */, + DA2E57EB3CB3312081676A46F7238B24 /* AdaptiveStyle.swift */, + F95AA7ACDE907999406636AE9140BF79 /* AdaptiveStyleTransformation.swift */, + 4E3D53C87F3183ECB9828E9F2CC13CEF /* AttributedStringTransformation.swift */, + 52C88D2EB51952A1D85A0AB4AD8FE1D6 /* Compatibility.swift */, + 5D93E1401B7CC5204F8F2112E6F2DF1A /* Composable.swift */, + 2707310D83A1EE6275AED80C0CF694FE /* ContextualAlternates.swift */, + B74880F26CD1B4204F6539C5B5502D2E /* EmbeddedTransformation.swift */, + A45D8D0A1979A555EFB7FFB40FE9E3B3 /* Emphasis.swift */, + 9EF280833555D9A6C3AB807C1BBEF193 /* FontFeatures.swift */, + E07B09F7C15576A3A444C774F45026FA /* FontInspector.swift */, + F44A4945BC33C7C54BB4A7520594B486 /* Image+Tinting.swift */, + 8C4EB1163B98FFAB7C42AB21C3ACF776 /* Ligatures.swift */, + 793A451BCFED3B0D33EF91ABA0E76DC0 /* MutableCopying.swift */, + 288D811BFAFF4D05B72871868528971C /* NamedStyles.swift */, + E4A4ECCE028DEB376DB17F98A1E4451E /* NSAttributedString+Adaptive.swift */, + EA27AEAA510EE20594C0FCF896C53040 /* NSAttributedString+BonMot.swift */, + E1FE7B5BE33FDB3387A107014CDD4C22 /* Platform.swift */, + 9E603AE6FAEA107641D9E8499AD28ACD /* Special.swift */, + 786594362231C88055784CE1F30F160D /* StringStyle.swift */, + 6E2CFBCCEE9CCE0907B805548198E2D4 /* StringStyle+Part.swift */, + F6E6EBF71B53225C8F92782A7CC19944 /* StyleableUIElement.swift */, + D33CE071F3F3081B71DA145EC68A99E8 /* StylisticAlternates.swift */, + 8FA9AF149F192E34E86DF398F93B6819 /* Tab.swift */, + 9457CFFC68284D195CF10F91CD0AB794 /* Tab+Adaptive.swift */, + 5112CE97A821E9C641D75D1ADAC3EB32 /* TextAlignmentConstraint.swift */, + BD6721E414F5E4895627210AFB5397AC /* Tracking.swift */, + 7852EA1E7C25798259AEA5BCE126639F /* Tracking+Adaptive.swift */, + 23F5E88F86F777E70C48C646149BA42B /* Transform.swift */, + 9D4DE2FA59344D4592D75A8D5A4137CE /* UIKit+AdaptableTextContainerSupport.swift */, + 547CDF4449B3AF5D1990F54FD639448E /* UIKit+Helpers.swift */, + DE1C7DAA26B8EA104B1A50DE2EC3AF35 /* XMLBuilder.swift */, + 1107F56DAC35E1270FAD72DE01F6E7C2 /* Support Files */, ); - name = Views; + name = BonMot; + path = BonMot; sourceTree = ""; }; - 7AA82BB4B120C4404FDE8101990218DC /* SimulatorStatusMagic */ = { + 52411C2325EA0E6639195CA9110A2234 /* AccessibilityHelpers */ = { isa = PBXGroup; children = ( - C615B52490F87ADAB2878CBBA62A49EE /* SDStatusBarManager.h */, - 600A0B900A253A3C1175F9E4D95DB5D0 /* SDStatusBarManager.m */, - E74DC75AECA924D9AA03636808FE7BDF /* SDStatusBarOverrider.h */, - 169E0A2C66830CE4D025F55BF0B70D78 /* SDStatusBarOverriderPost10_0.h */, - A6A3C66135761B8589F2EEC25372EA62 /* SDStatusBarOverriderPost10_0.m */, - F9E56C55E5C3E4C28EBF213499DC13B2 /* SDStatusBarOverriderPost10_3.h */, - B68AFDFA486327E986AA02A5299A8997 /* SDStatusBarOverriderPost10_3.m */, - 8ACDCF9FDA55A7DB7730D6DB537616F6 /* SDStatusBarOverriderPost11_0.h */, - BA2995A05285EE6DED3FEEA5F13AACF4 /* SDStatusBarOverriderPost11_0.m */, - 76574677F65789134324FB1D3C925091 /* SDStatusBarOverriderPost12_0.h */, - 61D71EA297A255FC6751524FC2D7AE30 /* SDStatusBarOverriderPost12_0.m */, - 828C42D1340C4F63C8F0F9D333CD612A /* SDStatusBarOverriderPost8_3.h */, - 6C4CA57B497201B0B30CAB96DDE10D16 /* SDStatusBarOverriderPost8_3.m */, - D8D0E31FC29539DB63B7901E4B473483 /* SDStatusBarOverriderPost9_0.h */, - 0E460FE658668EC518CCCB65C4F75F33 /* SDStatusBarOverriderPost9_0.m */, - 54B8EFB70012E9BEFC2371D3FF24AB1E /* SDStatusBarOverriderPost9_3.h */, - C3BD4ED7910EC78F54E9906021EAC11E /* SDStatusBarOverriderPost9_3.m */, - DFA0BCDC716C3C2DF6E46612791CA5FD /* SDStatusBarOverriderPre8_3.h */, - DFB0EC7EBB399F7D5A85850FD00CE2C4 /* SDStatusBarOverriderPre8_3.m */, - 24661EC968A27C8194E87D8F4C8DFEDA /* Support Files */, + 075A60A7C92F557056B739FD7E6BD32C /* AccessibilityHelpers.swift */, ); - name = SimulatorStatusMagic; - path = SimulatorStatusMagic; + name = AccessibilityHelpers; sourceTree = ""; }; - 7DB72A687CA6FFC2CC7CA2CDF4C99DB5 /* HairlineView */ = { + 524CDDEC3E70D2318C9B6BBF8351CCFF /* Frameworks */ = { isa = PBXGroup; children = ( - 0344F233E115ED3F7D904DC23394C60C /* HairlineView.swift */, + 0124BA8F81579A732104EE20E5A04876 /* AppCenterDistribute.framework */, ); - name = HairlineView; + name = Frameworks; sourceTree = ""; }; - 7E88B4398B0BCC533744D8F503F7A955 /* Deselection */ = { + 525AB3E395182778A970F9C5207657AD /* Support Files */ = { isa = PBXGroup; children = ( - 5175D0955C66D6BC673461F540D755E6 /* UIViewController+Deselection.swift */, + 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */, ); - name = Deselection; + name = "Support Files"; + path = "../Target Support Files/Firebase"; sourceTree = ""; }; - 7F9C09CAAED759953131AA6A0B723C4B /* Pods-Services */ = { + 5D975087B778CF0E10D511A544EC1BDC /* CoreDataStack */ = { isa = PBXGroup; children = ( - 2F6BE75B39581AB2EE6B4DFDF846086D /* Pods-Services.modulemap */, - B85FB8C2D1A62E349160A5994FAD2E98 /* Pods-Services-acknowledgements.markdown */, - A0C489DAD9337929C5181A707028C871 /* Pods-Services-acknowledgements.plist */, - 9AB95055F14CE265D5FB56048A2E19D1 /* Pods-Services-dummy.m */, - 3D44924F1DBF16C7E8D7BE1A271DFA34 /* Pods-Services-Info.plist */, - B897A3FA47CC0821B4DB6D3C2B7E99CB /* Pods-Services-umbrella.h */, - 2C2CF3EDAF2544698EB98DE619346902 /* Pods-Services.appstore.xcconfig */, - E172436BEA1AA48D80B4772E292D7D6F /* Pods-Services.debug.xcconfig */, - 763EA71849BAFD4F80AE0913CD8AEB09 /* Pods-Services.develop.xcconfig */, - DD20F29EDEBA60AED25F95B2CE422567 /* Pods-Services.sprint.xcconfig */, + A39DC1AB08D7C48D33B0213FC070EE91 /* CoreDataStack.swift */, ); - name = "Pods-Services"; - path = "Target Support Files/Pods-Services"; + name = CoreDataStack; sourceTree = ""; }; - 82FADD3E70AD782113055BE3A69C10C6 /* TableViewHelpers */ = { + 61E1FBD62BF31EF9C5C6FCF8C2475554 /* Support Files */ = { isa = PBXGroup; children = ( - 0B23ECB1A1FC9AA01FEB7FABD6E284E1 /* IndexPath+Extensions.swift */, - 47B116AABF6F54A2E56D0AA81C893247 /* TableSection.swift */, - BECFB2D89D8B3332F5F17C1CE83D7E8F /* UITableView+Extensions.swift */, + 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */, ); - name = TableViewHelpers; + name = "Support Files"; + path = "../Target Support Files/Instabug"; sourceTree = ""; }; - 86E9FE5029DF109803765A3AC8DFDF1B /* NSURLSession */ = { + 639C45A86FA428194EE4AA78ED28FDCC /* SwiftGen */ = { isa = PBXGroup; children = ( - C7ADD80B33BD1D3965F9685D011E653B /* NSURLRequest+HTTPBodyTesting.h */, - 0844167EF0604BA510C035ACDF453F20 /* NSURLRequest+HTTPBodyTesting.m */, - 287203EA6EB5EB516A7B9DE8645F0403 /* OHHTTPStubs+NSURLSessionConfiguration.m */, - 0B2E6AF6F88FDD1CE6C631AD781A61C9 /* OHHTTPStubsMethodSwizzling.h */, - 0C509062B34F03EFFC01A0972C94C56B /* OHHTTPStubsMethodSwizzling.m */, + 0399B942A602E396575791AC8C00C305 /* Support Files */, ); - name = NSURLSession; + name = SwiftGen; + path = SwiftGen; sourceTree = ""; }; - 894FF4186D0770CAA45D9AB44E192AEA /* Support Files */ = { + 658C4AB79E2F1A8A07EAE776B3CC23B7 /* Support Files */ = { isa = PBXGroup; children = ( - E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */, + E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/SwiftGen"; + path = "../Target Support Files/Crashlytics"; sourceTree = ""; }; - 89B5E2C0C1CA80E3D1A21B0866F1BE8D /* Support Files */ = { + 662F353757E6B7E31DA01A696E1A2E2C /* Support Files */ = { isa = PBXGroup; children = ( - 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */, + CCEEB9D362BE4122040EB3458E5009F9 /* FirebaseCore.modulemap */, + 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */, + A78104E9B1CB747B9ACC895D21681C1E /* FirebaseCore-dummy.m */, + D91C93EC98E43B5CACE58587FC5A08E4 /* FirebaseCore-Info.plist */, + F3787E17CA4EF4DC7B09E88A20DD9847 /* FirebaseCore-umbrella.h */, ); name = "Support Files"; - path = "../Target Support Files/Crashlytics"; + path = "../Target Support Files/FirebaseCore"; + sourceTree = ""; + }; + 6A4D2FEE841CDA2E21B0A6D31767C6E3 /* GoogleUtilities */ = { + isa = PBXGroup; + children = ( + 24067F61C33DB58975E3961238A8DDF5 /* AppDelegateSwizzler */, + 13EF57D50F79CFF13C4996257901FDCC /* Environment */, + 7B23925A72D583C0812A0471748128AD /* Logger */, + 22012F4F0899CC6365FA911D9C7ADA3E /* MethodSwizzler */, + 4C4557B4DD2C0EF6C0E4D60D96ADD8C3 /* Network */, + CEC3374FD169D13C3E074C43021D181B /* NSData+zlib */, + F52DE65EA93C92C1F1F94D5B0BC29E6A /* Reachability */, + 993188936FF4518DE583518FC0A00FFC /* Support Files */, + 3B2DC82F6FC98950B2D602286A0BA4DA /* UserDefaults */, + ); + name = GoogleUtilities; + path = GoogleUtilities; sourceTree = ""; }; - 8AF618AED8E42E2BC6E83B1DB406F646 /* GoogleAnalytics */ = { + 6BDBCD98184ECE9E56EC1D563CFE1CA1 /* FirebaseInstanceID */ = { isa = PBXGroup; children = ( - 7EA968D668E05238E14773825FCF5CF5 /* GAI.h */, - 9F0B5CEE4220ED99753109FF0C4554D4 /* GAIDictionaryBuilder.h */, - 3642AF4C5ABB338945962F45503807EE /* GAIEcommerceFields.h */, - 2DDC6450754D0AB3B48A89969F7CCE4C /* GAIEcommerceProduct.h */, - 6D5D69F8E132528B4DFF162031B38803 /* GAIEcommerceProductAction.h */, - D7C275922D24E9A31A6B5A520B32C8CD /* GAIEcommercePromotion.h */, - 708747111C024E9A7164DB43F2862C22 /* GAIFields.h */, - 63815B6D30E9C8BAA285DE33797AEF53 /* GAILogger.h */, - 8CC6C53D14EE42A9C007047A01C4DF1F /* GAITrackedViewController.h */, - 4DEA707B91546820EF3F5255BA544E4E /* GAITracker.h */, - 0621EC7551BC056E7A033F9FADDD109D /* Frameworks */, - 5423402C475D3886640C53E07B0412B2 /* Support Files */, - ); - name = GoogleAnalytics; - path = GoogleAnalytics; + 0D5C9E49FD0B96CC5F0A774F637668F2 /* FirebaseInstanceID.h */, + D46CD8B2E3B48A9900B0D54DC022F51E /* FIRIMessageCode.h */, + 677C759A60BA1A68EC54588ED16024FD /* FIRInstanceID.h */, + C513955DA0F2FA1EC966C5DCB86267DE /* FIRInstanceID.m */, + 10D13A0F900275F0E08660D22CBD3BD7 /* FIRInstanceID+Private.h */, + 18DE3A66023F031C118C9FA1671ACC93 /* FIRInstanceID+Private.m */, + 8F4E12C03F40438969454920C49D2013 /* FIRInstanceID_Private.h */, + 046CA33B599DC985AC83516113232E99 /* FIRInstanceIDAPNSInfo.h */, + 88B5959D5B7A3E36DDEF6EA561F00502 /* FIRInstanceIDAPNSInfo.m */, + CE04EB1BD0E0D76A2673A8C0C3366119 /* FIRInstanceIDAuthKeyChain.h */, + D5DE97AD0E8D2A97E134344E7227B548 /* FIRInstanceIDAuthKeyChain.m */, + 2B76802A61020D8F2FF87DBC22F95501 /* FIRInstanceIDAuthService.h */, + 781146DAC6F2B33CBAB88F5B7480DA3C /* FIRInstanceIDAuthService.m */, + B8D3618FE4C32D4ADBE22D247745AB5F /* FIRInstanceIDBackupExcludedPlist.h */, + 466630EDA0868AA0AB1CEBACE48F76AB /* FIRInstanceIDBackupExcludedPlist.m */, + E2E3405DF921FD6575E7698CA8B86D62 /* FIRInstanceIDCheckinPreferences.h */, + F7515C947EF6212592653822C53CC690 /* FIRInstanceIDCheckinPreferences.m */, + 8487A57EC520F91735649B13CF1455E4 /* FIRInstanceIDCheckinPreferences+Internal.h */, + 186880608DAD6477417FCC20081E68DF /* FIRInstanceIDCheckinPreferences+Internal.m */, + 1E28DADD6AFEF6A2BABCAA95C90585AE /* FIRInstanceIDCheckinPreferences_Private.h */, + 5215C876BC30D194764B41B21031B21F /* FIRInstanceIDCheckinService.h */, + 44001909662AEC3C8F8AB4E8044AB034 /* FIRInstanceIDCheckinService.m */, + DE6910A0DE802228534590DFC11D90C2 /* FIRInstanceIDCheckinStore.h */, + 0904254547F200171C92FAE60BF75E4B /* FIRInstanceIDCheckinStore.m */, + 9B49BB3E350F98DF8781264F7BB9D61B /* FIRInstanceIDCombinedHandler.h */, + 26880FF9FEB2270469CDC3F44CFC51BE /* FIRInstanceIDCombinedHandler.m */, + 11EF24F4E2A79E63296F2034D972DD0A /* FIRInstanceIDConstants.h */, + A48A79CAAFF110C87DF8BF807837AB83 /* FIRInstanceIDConstants.m */, + 30C8877C44A2A9CEF55FFA4B756AB34A /* FIRInstanceIDDefines.h */, + DB6E2DA2A7458E3619DF8D70A1EE9011 /* FIRInstanceIDKeychain.h */, + DB1194551671BF12886B8DECFEC28149 /* FIRInstanceIDKeychain.m */, + 1C37EAC158A77C4D6904556D7810ED89 /* FIRInstanceIDKeyPair.h */, + 56C526BDE19AC726B077CA91F4A3D248 /* FIRInstanceIDKeyPair.m */, + EA44C89EDF2C4365821C353514E832DF /* FIRInstanceIDKeyPairStore.h */, + 13811593551EEF5606EAEAC864156243 /* FIRInstanceIDKeyPairStore.m */, + F4539DEEA1DD2E3E786DAB20A235E0B9 /* FIRInstanceIDKeyPairUtilities.h */, + C5090975983CFFFD9CB40E0075C0D038 /* FIRInstanceIDKeyPairUtilities.m */, + BAEE38A7456029D2435589A2AB61BB54 /* FIRInstanceIDLogger.h */, + B348867894A4CE1D01EE3407670282AA /* FIRInstanceIDLogger.m */, + 9F64FB46C163A2D7EEDD531525ED4A3E /* FIRInstanceIDStore.h */, + 8F00E32E42A1E8D5237611B57EB97BFC /* FIRInstanceIDStore.m */, + 24FEA1649F859C025807618A170C83B1 /* FIRInstanceIDStringEncoding.h */, + EC198B2667B7ACBED262624C674F40C0 /* FIRInstanceIDStringEncoding.m */, + 78277DF682670FCB6D1E611B6DD72010 /* FIRInstanceIDTokenDeleteOperation.h */, + B94ED403343770A491208CD276342FF7 /* FIRInstanceIDTokenDeleteOperation.m */, + 5FD4F06E7B97586342DC5F130C93CAD6 /* FIRInstanceIDTokenFetchOperation.h */, + FD58305059DB6EF784EF634B198DD3CB /* FIRInstanceIDTokenFetchOperation.m */, + 5AC714289EA97E67199CA997655EAF27 /* FIRInstanceIDTokenInfo.h */, + 55C1593407CAC28F4349FBA65B0C1BD9 /* FIRInstanceIDTokenInfo.m */, + B80D74D41E215EDC00F1A0D8245EC63E /* FIRInstanceIDTokenManager.h */, + 661D315940B1DDA7A83242BBBB7CFCA3 /* FIRInstanceIDTokenManager.m */, + 6F5FE5A0393B7EA11DA9DBF03DDF5479 /* FIRInstanceIDTokenOperation.h */, + 08DA9B3BA661AA7124AE37AFA1396048 /* FIRInstanceIDTokenOperation.m */, + 571718858875E6D21B448DAAA8A43D00 /* FIRInstanceIDTokenOperation+Private.h */, + 7DF524EA9012A4ACFCAD0BF6C7247299 /* FIRInstanceIDTokenStore.h */, + 3739B5667A1C1B8452C08E5FB55014E5 /* FIRInstanceIDTokenStore.m */, + 0E1E27256DFC0F8898600F8DA01A1D3E /* FIRInstanceIDURLQueryItem.h */, + 45BCED46E7DDF7FBA46DB0CC8B1E58EB /* FIRInstanceIDURLQueryItem.m */, + A3AA81B96ABF2101A80128229B5253C0 /* FIRInstanceIDUtilities.h */, + F1EB3FA695D6D0C669DA36186435E474 /* FIRInstanceIDUtilities.m */, + 4B0940BB70F444E65F6DB52323B97369 /* FIRInstanceIDVersionUtilities.h */, + E90EB60C7D8B2CBCC777305E2D53F83F /* FIRInstanceIDVersionUtilities.m */, + 7E542A623F5A954B3F4D243CF8A4FB46 /* NSError+FIRInstanceID.h */, + 6EB8515E357A8EA23661EBCD579561C3 /* NSError+FIRInstanceID.m */, + E81AD734C1E0D7D9E60EBB121AB226B1 /* Support Files */, + ); + name = FirebaseInstanceID; + path = FirebaseInstanceID; sourceTree = ""; }; - 8BA8F16C1557A2651F85FD88687831C3 /* StackViewHelpers */ = { + 6D2197C24F0848C862E51C94CF51A420 /* StackViewHelpers */ = { isa = PBXGroup; children = ( - 473B67F1C327A540855E3FC4CDFA3DEE /* UIStackView+Helpers.swift */, + E5A2D89B160FEBC3EA6D9A26612606E7 /* UIStackView+Helpers.swift */, ); name = StackViewHelpers; sourceTree = ""; }; - 8BEBB723F2EAEC9B427692EE1269E5B3 /* Fabric */ = { + 6F3EF0FA0969EBD80C6F4351AE01874E /* AppCenter */ = { isa = PBXGroup; children = ( - 04E11008993CDF01137A6258C64C7633 /* FABAttributes.h */, - F39A38B8C8A7A15B87AEB9C6DE99AA9F /* Fabric.h */, - B299A58FA5D14DD68F2B2317109A4C67 /* Frameworks */, - 4F64DC591F8303AA1CF2D7BC16037F93 /* Support Files */, + 7093ACAC5F51DA6AC7991BED779FAA8F /* Core */, + 28FF4F61E9D98CE24E3756A1DB302AA4 /* Distribute */, + 2516CFCC31378C0E7AD42AB3AEFD5046 /* Support Files */, ); - name = Fabric; - path = Fabric; + name = AppCenter; + path = AppCenter; sourceTree = ""; }; - 97307F8DFE50452DE7A84E768AD3DE3E /* SwiftLint */ = { + 6F7FBCC6A736AEF8531F507FBD9838DA /* encode */ = { isa = PBXGroup; children = ( - 3C3C7D9D5069BE48050495089CB0C052 /* Support Files */, ); - name = SwiftLint; - path = SwiftLint; + name = encode; sourceTree = ""; }; - 98F6046110197DC3661BBBA12005FD56 /* Pods-PRODUCTNAME */ = { + 7093ACAC5F51DA6AC7991BED779FAA8F /* Core */ = { isa = PBXGroup; children = ( - 49442838275784AC430968A99E9197D0 /* Pods-PRODUCTNAME.modulemap */, - A3AE46141D0D4C9B24ABA5B528FA5352 /* Pods-PRODUCTNAME-acknowledgements.markdown */, - 5CB62BF9A996328D3C7FD3E03A32F740 /* Pods-PRODUCTNAME-acknowledgements.plist */, - FD33C68E323DA2EF0D6FAE8737B0BD1D /* Pods-PRODUCTNAME-dummy.m */, - 3883E78F24323AF243E39A35CED0B383 /* Pods-PRODUCTNAME-frameworks.sh */, - A789E28B8BC1DFFB04379D3F52042939 /* Pods-PRODUCTNAME-Info.plist */, - E7FE233BF7FEEB9A8A795679328F0C82 /* Pods-PRODUCTNAME-umbrella.h */, - 762B6EA59AD44657FC4F6F155EE84D81 /* Pods-PRODUCTNAME.appstore.xcconfig */, - F8EB17459DA65ED2256E7DD16A25905C /* Pods-PRODUCTNAME.debug.xcconfig */, - B4E5336742C14FD6B50FD57C94F7E2EF /* Pods-PRODUCTNAME.develop.xcconfig */, - 88BA0595C84DF09AE03104A4BDD671A8 /* Pods-PRODUCTNAME.sprint.xcconfig */, + A8D54C77C0BEB46D88F469145C20DE6C /* Frameworks */, ); - name = "Pods-PRODUCTNAME"; - path = "Target Support Files/Pods-PRODUCTNAME"; + name = Core; sourceTree = ""; }; - 99A9FB604757E09F2687BB44D3042A5B /* Shapes */ = { + 788A2F1337113677CD6B6F0562BEACE1 /* Support Files */ = { isa = PBXGroup; children = ( - 97594C320B5EFC4497444BB58291142A /* Shapes.swift */, + 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */, ); - name = Shapes; + name = "Support Files"; + path = "../Target Support Files/Sourcery"; sourceTree = ""; }; - 9D4A2B374C2CA7D663F4F8742572279B /* TintedButton */ = { + 7A06EBF1D3AE62AED0DC085715332089 /* Pods-Services */ = { isa = PBXGroup; children = ( - 171475FCE61CF50AA00728DC54688438 /* TintedButton.swift */, + C84BD906EE42E9D43CBC7AE02AA3C2E3 /* Pods-Services.modulemap */, + 2B6941F28C59EA39D79CAAF8560210A4 /* Pods-Services-acknowledgements.markdown */, + 1FC6D095DAD42D44CCD8E75BCB2FE43F /* Pods-Services-acknowledgements.plist */, + AF4C07CB531C2A20C075F1E2F27F9807 /* Pods-Services-dummy.m */, + 73D447A7F190F1E1C93B83CA52F803B4 /* Pods-Services-Info.plist */, + 43F95FB28B3B3DDC58B3E70C591BD759 /* Pods-Services-umbrella.h */, + 1987EE9FAD1DBEC74F2716EA5DC6B2D0 /* Pods-Services.appstore.xcconfig */, + 63202DA0FE6824272136B2EC50F9FB63 /* Pods-Services.debug.xcconfig */, + 1358F7B95EC32C0D0017CE9DBF481067 /* Pods-Services.develop.xcconfig */, + FA50610602A727B99D7294CFF81CC8E8 /* Pods-Services.sprint.xcconfig */, ); - name = TintedButton; + name = "Pods-Services"; + path = "Target Support Files/Pods-Services"; sourceTree = ""; }; - AA2D4B4B69EDBD35E7D335D97828D7E9 /* Forms */ = { + 7B0CC8495563F9B10D302FDF8BE31E73 /* nanopb */ = { isa = PBXGroup; children = ( - B81E944F8B0AEB55DC7130BCF5D0265E /* FieldValidator.swift */, - 0D9B5EA89BF66F54C9437D2204EC0D69 /* UIView+Lookup.swift */, - ); - name = Forms; + C146F3AD61FC35B7C5ACADB293B2E5CF /* pb.h */, + E458A4DC6C3E79475F17EE8A2379E327 /* pb_common.c */, + 63782DD22D80D12F0478617EBF8A6E9E /* pb_common.h */, + BBF0EE4B9DF20FB5E0DF535FED448A7E /* pb_decode.c */, + 322D077B4897B4E6A8C083170A121575 /* pb_decode.h */, + BDF0BD64F7D053FC261E77000D9D5B27 /* pb_encode.c */, + E862D618BF042EA8A06C94B566412A7A /* pb_encode.h */, + FBB07FC05F11C073D5B30FFFF4FB1787 /* decode */, + 6F7FBCC6A736AEF8531F507FBD9838DA /* encode */, + 230DD97E2682539EBF5CBB6EFCAB3D1B /* Support Files */, + ); + name = nanopb; + path = nanopb; sourceTree = ""; }; - AC01D6C29F288E9B876B6D64EC05ADA8 /* Support Files */ = { + 7B23925A72D583C0812A0471748128AD /* Logger */ = { isa = PBXGroup; children = ( - 76B2C8862CEAB7ED9309B5842CD243A2 /* OHHTTPStubs.modulemap */, - BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */, - EB19F16C37CD2E91D6E593747C7AF54F /* OHHTTPStubs-dummy.m */, - 3198255E8CC28000CEAA0676F48D77BA /* OHHTTPStubs-Info.plist */, - E3C4C1F6B36E0BECB296C1483D026F54 /* OHHTTPStubs-prefix.pch */, - D1715D98301B1F97137AD0E551489F6C /* OHHTTPStubs-umbrella.h */, + 15D1AB7F35E8D9D69E2A3E30D0AFA1F1 /* GULLogger.h */, + 319AFABD7CD5670EEEE2D2BA15A360BD /* GULLogger.m */, + 2D45D29B213853B66B8B282991CCF083 /* GULLoggerLevel.h */, ); - name = "Support Files"; - path = "../Target Support Files/OHHTTPStubs"; + name = Logger; sourceTree = ""; }; - AFE36D973A8766E9A3168E44925B8BAB /* Pods */ = { + 7F7F3C5E8428F9EC082EB77C8B6C0743 /* Pods-PRODUCTNAME */ = { isa = PBXGroup; children = ( - 0CF4592BE7C00EC061DDC98F28B45103 /* Alamofire */, - DE8C6E9CFF09DDBE243CFCA29A440F97 /* Anchorage */, - 6D002A39BF8CFC58BD0D07E789AD8401 /* BonMot */, - 6BE7F2180A18F22C70A19933BCED7310 /* Crashlytics */, - 8BEBB723F2EAEC9B427692EE1269E5B3 /* Fabric */, - 8AF618AED8E42E2BC6E83B1DB406F646 /* GoogleAnalytics */, - F8B2417C84920C04BF6090E0D97234F6 /* Instabug */, - DA6CEA4CC798218DC37749B3DBA60998 /* KeychainAccess */, - 4C5E989981AF2A86EAE4FC8874303A39 /* OHHTTPStubs */, - 7AA82BB4B120C4404FDE8101990218DC /* SimulatorStatusMagic */, - 2F509B4DFD1746DF49A4CBE5A55099B6 /* Sourcery */, - EEA965888C48D6DC3E9C314F30DA0710 /* SwiftGen */, - D79FFA981B4E1F3909EBEE0F4A85691E /* Swiftilities */, - 97307F8DFE50452DE7A84E768AD3DE3E /* SwiftLint */, + B5579787CFCE1BC97D5EF0CCEB731C04 /* Pods-PRODUCTNAME.modulemap */, + C1CD6931566B12098A093FE863131A16 /* Pods-PRODUCTNAME-acknowledgements.markdown */, + 2DE296C57E7600238C8BE1E7BEE31B00 /* Pods-PRODUCTNAME-acknowledgements.plist */, + 9A572C6721447ABE0F589A4004BA6EFA /* Pods-PRODUCTNAME-dummy.m */, + 598E11382120CC7243651B55798ADF64 /* Pods-PRODUCTNAME-frameworks.sh */, + 32FC646A39309A016A43413CF59D0AB3 /* Pods-PRODUCTNAME-Info.plist */, + A1718A38D1F7426976B72AE548700F4E /* Pods-PRODUCTNAME-resources.sh */, + 8F63F7236794D312ACB1F32E2BE55CA4 /* Pods-PRODUCTNAME-umbrella.h */, + C4B85119F40EE2D53CF9459420F29B53 /* Pods-PRODUCTNAME.appstore.xcconfig */, + 8CC134AECB569C629CF74E270D3E8FC3 /* Pods-PRODUCTNAME.debug.xcconfig */, + 4C3439A40A51D1DD58761BACB9331DD2 /* Pods-PRODUCTNAME.develop.xcconfig */, + 518BACD57DCD1AA45BE9270B8C5CF1B5 /* Pods-PRODUCTNAME.sprint.xcconfig */, ); - name = Pods; + name = "Pods-PRODUCTNAME"; + path = "Target Support Files/Pods-PRODUCTNAME"; sourceTree = ""; }; - B299A58FA5D14DD68F2B2317109A4C67 /* Frameworks */ = { + 8275CCB4E8732497B1021FCBC240F3C2 /* Frameworks */ = { isa = PBXGroup; children = ( - 8CA7CEF2E4E333C866B0744A716DBC48 /* Fabric.framework */, + 008F623D5F4F4DAC4CE6F23C456144BD /* iOS */, ); name = Frameworks; sourceTree = ""; }; - B63DCDF704E0788DC63109591DD5E134 /* Logging */ = { + 82C0081EC4C54F0E3B87CF4659B2C78B /* GoogleAppMeasurement */ = { isa = PBXGroup; children = ( - CFD134FCA91FFE97E31F5E29CF515503 /* Log.swift */, + E101FC07342B02BB434763AB5503FDF0 /* Frameworks */, + B73AC685A73B7CABCDF13699741B1462 /* Support Files */, ); - name = Logging; + name = GoogleAppMeasurement; + path = GoogleAppMeasurement; sourceTree = ""; }; - B77847F620609B954972201E68BBBF34 /* Support Files */ = { + 85904E31CC5A94E382F8A1C5377D2253 /* Frameworks */ = { isa = PBXGroup; children = ( - C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */, + 8EA90B335493CD691AF6F92A19615597 /* FIRAnalyticsConnector.framework */, + 82C3962E95811D63FBFBD722F2BD0204 /* FirebaseAnalytics.framework */, + 5BA55509BAF2F35EE0DDC61B513006A6 /* FirebaseCoreDiagnostics.framework */, ); - name = "Support Files"; - path = "../Target Support Files/Sourcery"; + name = Frameworks; sourceTree = ""; }; - B94D7768568A9992200DB461E8CF687F /* Frameworks */ = { + 8685EDF6DBF9F3844A945C3B5F860AB9 /* AboutView */ = { isa = PBXGroup; children = ( - DAF2540B0FC2773A666D28B59AFF608D /* iOS */, + 6F446B65463479D1A1BC7E615FB1DB21 /* AboutView.swift */, + 829A957DF3BA4C53A538E446773D71B8 /* AppInfo.swift */, + 6228C304CE54B8A03AEF3954707FB619 /* FeedbackPresenter.swift */, ); - name = Frameworks; + name = AboutView; sourceTree = ""; }; - C45061ABD2B10050498CBDC9C61914A5 /* Keyboard */ = { + 872C1397FD565D4C0B9EFDBBCED2AAAF /* TableViewHelpers */ = { isa = PBXGroup; children = ( - FA462C4F41ADFF2B1F485CA4D300A507 /* Keyboard.swift */, - 16618C3BC05BC3E526CD791AA381BFB3 /* UIView+KeyboardLayoutGuide.swift */, + 6605561032963C6225A616C84441A72F /* IndexPath+Extensions.swift */, + 245165C00B0AB8EFA8DF3D2BBC1F3C8D /* TableSection.swift */, + 552F3B93D76BA12F543F0275D11FB3F6 /* UITableView+Extensions.swift */, ); - name = Keyboard; + name = TableViewHelpers; sourceTree = ""; }; - C9DF2F99BD018938BF6E5E89BBE53EDA /* Support Files */ = { + 8A454DADBEB04B4D31A42E8DFBD25E37 /* SwiftLint */ = { isa = PBXGroup; children = ( - D028177281860E86C9025064AAD7903C /* Swiftilities.modulemap */, - 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */, - 423575D637674B034C086A88A750516A /* Swiftilities-dummy.m */, - B0F981FC5A6AC94677657E5363CB9F6E /* Swiftilities-Info.plist */, - 66BCBFC05E4D8780FD4246F0345294C9 /* Swiftilities-prefix.pch */, - 289F895A731229C94D7D07DFD3480E56 /* Swiftilities-umbrella.h */, + 02309E965B34DCCD4D31C8903492D26F /* Support Files */, ); - name = "Support Files"; - path = "../Target Support Files/Swiftilities"; + name = SwiftLint; + path = SwiftLint; sourceTree = ""; }; - CF1408CF629C7361332E53B88F7BD30C = { + 8B8A98ECF03760402D075F38389B3988 /* TintedButton */ = { isa = PBXGroup; children = ( - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - B94D7768568A9992200DB461E8CF687F /* Frameworks */, - AFE36D973A8766E9A3168E44925B8BAB /* Pods */, - 4F93E6BFC4CC76D46B72C7BD14EEAB83 /* Products */, - 55A4C5822968D07AACCB2DE35D1D4A4C /* Targets Support Files */, + 3F5BB4D560F726BDE1F35DA184B1268B /* TintedButton.swift */, ); + name = TintedButton; sourceTree = ""; }; - D1973AC097C0D79EE13297A9936A01DA /* BetterButton */ = { + 8BDFEEE65FACF169A2EB85AE06AD1146 /* Pods-PRODUCTNAME-PRODUCTNAMETests */ = { isa = PBXGroup; children = ( - 47CB2C8C52E2A4F6F847C2D4939E36B1 /* BetterButton.swift */, + 422359491E6C68A5FEFC4E916C0385EF /* Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap */, + 39011BD939C3832DBBFC0228D3EF5804 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown */, + AF915886F12CE018C123DBCE8092ECC5 /* Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist */, + 7E629EB70356C8FA1AD9781584EA8374 /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m */, + 95728BB595EBF3C2595CF132C9C7AAAC /* Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh */, + 16C9E7ABD2EF227BB7684A8307667F72 /* Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist */, + 781DC562E9BB6624DE3FB5B273AEF265 /* Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh */, + C395986E3E5F5139E1E2D48B13C6B14A /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h */, + 3CE8A623704EA768F5F5576533B75CC4 /* Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig */, + 300E24828164112EB400CCFD1E0D55B9 /* Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig */, + FCBFF9345F652100273AE93760F66435 /* Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig */, + 7B31944D9854B90AB402DAEBC2714BCB /* Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig */, ); - name = BetterButton; + name = "Pods-PRODUCTNAME-PRODUCTNAMETests"; + path = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests"; sourceTree = ""; }; - D41B1FB075B7B8972717CC6236282BF8 /* Support Files */ = { + 8D527B9C3DE0F3C4790F2C72704D59DC /* Pods */ = { isa = PBXGroup; children = ( - 8A2B8AA86BCE7F70AAAF10D276187F76 /* BonMot.modulemap */, - B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */, - CACC82C9360F0099F26C79E3B2059185 /* BonMot-dummy.m */, - 29ABD7B829A0C25AC36C7EDE2458B4C1 /* BonMot-Info.plist */, - 582BD27DFB831D016846914FEDC4084D /* BonMot-prefix.pch */, - C580B89A921E19C037BD54E71FF73A6A /* BonMot-umbrella.h */, + BC59AFE25F73D0ABD159E379B3DA14B5 /* Alamofire */, + AE6F222D95639EFAB3F51992DA3BAEB5 /* Anchorage */, + 6F3EF0FA0969EBD80C6F4351AE01874E /* AppCenter */, + 51A6420B90C1B77281AFA830BC68F078 /* BonMot */, + 009380C89EA1FF9D5353746EAEF1EEED /* Crashlytics */, + AAE112D8EBCF66234755E03D80A66A35 /* Fabric */, + 1C939FBA6FABCCA30B1290EE3ACA9D09 /* Firebase */, + 8D59FF043DE5F5E40B310E41E371B2B0 /* FirebaseAnalytics */, + 03C52F83D51E179A4C50733DEECC309F /* FirebaseAnalyticsInterop */, + D5A1FC161D50AE992042E65485320E60 /* FirebaseCore */, + 6BDBCD98184ECE9E56EC1D563CFE1CA1 /* FirebaseInstanceID */, + 2F42D4BF0DDF237686424E3A4EF51E70 /* FirebaseMessaging */, + 82C0081EC4C54F0E3B87CF4659B2C78B /* GoogleAppMeasurement */, + 6A4D2FEE841CDA2E21B0A6D31767C6E3 /* GoogleUtilities */, + C59A82E1D6A01A9AEE70D0221E9593F7 /* Instabug */, + 05B1CA5F6FC7AE0E1EC3D2B58262045F /* KeychainAccess */, + 7B0CC8495563F9B10D302FDF8BE31E73 /* nanopb */, + 1CA59AED19FCBF816340C45A5F720DFF /* OHHTTPStubs */, + 37EAF90413960A018228B0E598F8F0EA /* Protobuf */, + 2BC40A9034E168E418BAA7541218D456 /* SimulatorStatusMagic */, + 008F18918E7698B497FF8188729031AD /* Sourcery */, + 639C45A86FA428194EE4AA78ED28FDCC /* SwiftGen */, + 1B6124501CF65ED3F6A2AD1A93DBAC2D /* Swiftilities */, + 8A454DADBEB04B4D31A42E8DFBD25E37 /* SwiftLint */, ); - name = "Support Files"; - path = "../Target Support Files/BonMot"; + name = Pods; sourceTree = ""; }; - D79FFA981B4E1F3909EBEE0F4A85691E /* Swiftilities */ = { + 8D59FF043DE5F5E40B310E41E371B2B0 /* FirebaseAnalytics */ = { isa = PBXGroup; children = ( - 6E76B52DFE8B416AC422A204899827B0 /* AboutView */, - DFBCE835344E402246E16055311AE39D /* AccessibilityHelpers */, - 485E8618AF9F5DF813FB9AD3394C9F98 /* Acknowledgements */, - D1973AC097C0D79EE13297A9936A01DA /* BetterButton */, - EA1E67FE7CC5AB9D1D6B30EA309A781D /* ColorHelpers */, - 0A3AD2032D53BB89BD7F0CF156B13F29 /* Compatibility */, - 52D0F86B31D357565D421D4C5DC1BB3C /* CoreDataStack */, - 7E88B4398B0BCC533744D8F503F7A955 /* Deselection */, - 3CB3DA0AFA5A77F95FBA304DFB8BE9E3 /* DeviceSize */, - 03FF892223A1929709776BF7189E75D9 /* FormattedTextField */, - AA2D4B4B69EDBD35E7D335D97828D7E9 /* Forms */, - 7DB72A687CA6FFC2CC7CA2CDF4C99DB5 /* HairlineView */, - 10940FBD6FB6D853861B1B2B407921CA /* ImageHelpers */, - C45061ABD2B10050498CBDC9C61914A5 /* Keyboard */, - 37E1736714D26724253BBD4361E48477 /* LicenseFormatter */, - 120CF486BAFD376244CEE1879E7EBC96 /* Lifecycle */, - B63DCDF704E0788DC63109591DD5E134 /* Logging */, - 715EFDE146C70BF40DC2D065C60FB4AF /* Math */, - 434B27B3D4D39B0FFE9CC5249CE90B07 /* RootViewController */, - 99A9FB604757E09F2687BB44D3042A5B /* Shapes */, - 8BA8F16C1557A2651F85FD88687831C3 /* StackViewHelpers */, - C9DF2F99BD018938BF6E5E89BBE53EDA /* Support Files */, - 82FADD3E70AD782113055BE3A69C10C6 /* TableViewHelpers */, - 9D4A2B374C2CA7D663F4F8742572279B /* TintedButton */, - 719130B020D019BAB5B597C067CBB10D /* Views */, + 85904E31CC5A94E382F8A1C5377D2253 /* Frameworks */, + F7114582B168E212D19780C5CCFBEC19 /* Support Files */, ); - name = Swiftilities; - path = Swiftilities; + name = FirebaseAnalytics; + path = FirebaseAnalytics; sourceTree = ""; }; - DA6CEA4CC798218DC37749B3DBA60998 /* KeychainAccess */ = { + 8FECC04822D33D646019B4479EA366F9 /* Keyboard */ = { isa = PBXGroup; children = ( - 8A56048850B5EB8CF23F6DAD9C06FBF7 /* Keychain.swift */, - 2C290985CBE0A9B5FAE7C9FE0A6F42A9 /* Support Files */, + 7558233F38BB01572FA6F6C87087DE05 /* Keyboard.swift */, + 365D0C4EEEA6C8DB030220CF3E73772A /* UIView+KeyboardLayoutGuide.swift */, ); - name = KeychainAccess; - path = KeychainAccess; + name = Keyboard; sourceTree = ""; }; - DAF2540B0FC2773A666D28B59AFF608D /* iOS */ = { + 972401FA47F7EB697BFBC5DE4DAA0651 /* Frameworks */ = { isa = PBXGroup; children = ( - CBA24296CBFCC1AB1BC5AB37A4F7BD49 /* CFNetwork.framework */, - B67E5A3B83075128A1543C2893FF8978 /* CoreData.framework */, - 124575BF48673080C3D4899F5B3A5B8B /* Foundation.framework */, - 3F338A55DD7E095C1009887CED6DC4AC /* MessageUI.framework */, - E17F1FA7E71417208B484A6B4798DDD6 /* UIKit.framework */, + 0B8FDDE48F44189CC0D2FC2CAA0D5C49 /* Crashlytics.framework */, ); - name = iOS; + name = Frameworks; sourceTree = ""; }; - DE8C6E9CFF09DDBE243CFCA29A440F97 /* Anchorage */ = { + 989DC329BA99D7559AF31C340D4FB904 /* ImageHelpers */ = { isa = PBXGroup; children = ( - BCDA5E72258FCCDB8B342B3D19FF405C /* Anchorage.swift */, - 6850346376F7BEE1EB250B890DCBE0BF /* AnchorGroupProvider.swift */, - 9270993480FEDFD0F12D1749E45B20D3 /* Compatability.swift */, - CE1ABD0449009E446A4D3F9A93FC4DEB /* Internal.swift */, - EC1AF230CF867C88C770CE9C374EA4A9 /* NSLayoutAnchor+MultiplierConstraints.swift */, - 78D61CCC7F7CA3A111C6C359B619EFD6 /* Priority.swift */, - 281478A870268B2E3D4118E01D17010B /* Support Files */, + B8E677CF6BD8B668E00639F75526D6FE /* UIImage+Tinting.swift */, ); - name = Anchorage; - path = Anchorage; + name = ImageHelpers; sourceTree = ""; }; - DFBCE835344E402246E16055311AE39D /* AccessibilityHelpers */ = { + 993188936FF4518DE583518FC0A00FFC /* Support Files */ = { isa = PBXGroup; children = ( - CB38C12AE406FDC85937CCF35845E787 /* AccessibilityHelpers.swift */, + 7FF09D8EFD37D437525F039619D3D763 /* GoogleUtilities.modulemap */, + 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */, + 44CE758ABDDC428058091BE3EF7C9451 /* GoogleUtilities-dummy.m */, + 4D0B98AEB62ED9CED697D20516060929 /* GoogleUtilities-Info.plist */, + 233D6E7BF9D19F75FCD75EB9691646DB /* GoogleUtilities-prefix.pch */, + A64AD290563189B5EC09536986EEA27C /* GoogleUtilities-umbrella.h */, ); - name = AccessibilityHelpers; + name = "Support Files"; + path = "../Target Support Files/GoogleUtilities"; sourceTree = ""; }; - E03F86A5298A02EDA71AD21D5CC0C456 /* Swift */ = { + 9AC8E57272E0D480F3376E031CF9D360 /* HairlineView */ = { isa = PBXGroup; children = ( - EE18F1B83B66E2F8033DD4F4C792ED8A /* OHHTTPStubsSwift.swift */, + 9435CEF7CA7BCE866E215F71262E51F6 /* HairlineView.swift */, ); - name = Swift; + name = HairlineView; sourceTree = ""; }; - EA1E67FE7CC5AB9D1D6B30EA309A781D /* ColorHelpers */ = { + 9B39C83358AAA4C9B0BE04FCA31A4DD4 /* Support Files */ = { isa = PBXGroup; children = ( - ADA69A7B37937B271062924B815424C5 /* UIColor+Helpers.swift */, + 80F2752CD15387DAD8075D0DE08C9A48 /* SimulatorStatusMagic.modulemap */, + 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */, + 6EBEFE4F4DF5F7C86F8F3F2C30FC2380 /* SimulatorStatusMagic-dummy.m */, + 84DA61DFF1F0980689DC3F498047D530 /* SimulatorStatusMagic-Info.plist */, + 7579D1AD4020ED9620DFC5844850FF1E /* SimulatorStatusMagic-prefix.pch */, + 422661E817D097522D8B376CDBD2FD9C /* SimulatorStatusMagic-umbrella.h */, ); - name = ColorHelpers; + name = "Support Files"; + path = "../Target Support Files/SimulatorStatusMagic"; sourceTree = ""; }; - EEA965888C48D6DC3E9C314F30DA0710 /* SwiftGen */ = { + 9EC0439B0FC7C4EEE4048EF00565EA88 /* Frameworks */ = { isa = PBXGroup; children = ( - 894FF4186D0770CAA45D9AB44E192AEA /* Support Files */, + C382C33DB25925C6186211ACF6C39C64 /* Fabric.framework */, ); - name = SwiftGen; - path = SwiftGen; + name = Frameworks; sourceTree = ""; }; - F59A8AD80AFFA490B6A45C134478C1C1 /* Support Files */ = { + 9F3FB97F3B837239BF3776F5642D3884 /* OHPathHelpers */ = { isa = PBXGroup; children = ( - 6BC0330C6905084757112A6626DEA435 /* Alamofire.modulemap */, - 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */, - 957FC6AC38169C7173562AA6E6597C5A /* Alamofire-dummy.m */, - B4C9173AAD69C5F900F070C2DC393F90 /* Alamofire-Info.plist */, - B633536FE6BDE55D4B91A7795F4FF80E /* Alamofire-prefix.pch */, - E37EC6963507772140141310564C96A7 /* Alamofire-umbrella.h */, + F582E21899CB1B7DD3C29A9B5AB73287 /* OHPathHelpers.h */, + 894FB1F3B5CAA20D3A8E5DA58FA415A3 /* OHPathHelpers.m */, ); - name = "Support Files"; - path = "../Target Support Files/Alamofire"; + name = OHPathHelpers; sourceTree = ""; }; - F8B2417C84920C04BF6090E0D97234F6 /* Instabug */ = { + A0704D01E12AD83ADCAF5B229CE99161 /* Shapes */ = { isa = PBXGroup; children = ( - 03BB3A2B2382C9AECA1345DF10758FF7 /* IBGBugReporting.h */, - 6C8D7031183605564560F8C005274726 /* IBGChats.h */, - D6A7ADC89E5C649F8CA13967D02858A9 /* IBGCrashReporting.h */, - 2927977169D5E8824B1B0F49F29DCDB7 /* IBGFeatureRequests.h */, - 08D058A0428C1C703F302390940EB70D /* IBGLog.h */, - 71BC06C450F39A6C28917FDFD2D3D3A4 /* IBGNetworkLogger.h */, - CAC7B89760289277486CBA8E128C3E83 /* IBGReplies.h */, - 7E363AC19B8D721F73D148E1225011D9 /* IBGReport.h */, - 1C61F5CB85EBA2E536ABB3FACB92C14D /* IBGSurvey.h */, - 2814252E46C1C3D835FC3766FA37E50B /* IBGSurveys.h */, - E382E277E58CBB6C6EA0E889BBC6490F /* IBGTypes.h */, - F0031BCA4B2C3DB8E91F1EECDFBE1285 /* Instabug.h */, - 2E8DEEC8D4E92C46491262BFEFD046CC /* InstabugCore.h */, - FF6FA5A59381E1B6E4E4C836E4DC3E8B /* UIView+Instabug.h */, - FA5935C7EA7F05D5E1E08F3CB73CFE9B /* Frameworks */, - 5E3C3393E847FDA37FAEBF7E00DDE1F4 /* Support Files */, + FCD38CBF4748B96190468E88F12A2064 /* Shapes.swift */, ); - name = Instabug; - path = Instabug; + name = Shapes; sourceTree = ""; }; - FA5935C7EA7F05D5E1E08F3CB73CFE9B /* Frameworks */ = { + A253B1E80FBA3C2BDD64EBC7F7DA3107 /* Forms */ = { isa = PBXGroup; children = ( - 0D5FCA72714F0B65331606F33C76F18A /* Instabug.framework */, + CE2FA012779DEECE2BC6CC90C6E90407 /* FieldValidator.swift */, + A52569BDA16818151E3735016A95C16B /* UIView+Lookup.swift */, ); - name = Frameworks; + name = Forms; sourceTree = ""; }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 039BBE20CB777B0B7B5E40A54A63D4BB /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 1DE5C075140703A862F18A6426944EC2 /* BonMot-umbrella.h in Headers */, + A2BA946DCE676E2A736992A6D7F61F5D /* Support Files */ = { + isa = PBXGroup; + children = ( + 89A489E0FEA5C5815748A7017DDB2666 /* FirebaseMessaging.modulemap */, + F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */, + 1F16A3F715737A448BD6736FC7CE8C23 /* FirebaseMessaging-dummy.m */, + 5099DC3344B97A39551F2FD82C61B62E /* FirebaseMessaging-Info.plist */, + C9AE3F8C3C621FD1D0196F941D21A520 /* FirebaseMessaging-umbrella.h */, ); - runOnlyForDeploymentPostprocessing = 0; + name = "Support Files"; + path = "../Target Support Files/FirebaseMessaging"; + sourceTree = ""; }; - 46DA116D0F3AF61E855459946FCE7335 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 4B72D0B7634016622F476687729A18C8 /* KeychainAccess-umbrella.h in Headers */, + A303943FD81E6344A959EF2275877C3B /* Support Files */ = { + isa = PBXGroup; + children = ( + 1546A7379CB47F23D0B23E42B46F302D /* Swiftilities.modulemap */, + BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */, + 016ABA6E4EC051693A5A08A27FAAA7DC /* Swiftilities-dummy.m */, + 346C27A97925A47261C4B6AC76983CD3 /* Swiftilities-Info.plist */, + FA555490178D1D5AE635B8B28338E254 /* Swiftilities-prefix.pch */, + 88F89AA47577A480D576C38E3EDFADAA /* Swiftilities-umbrella.h */, ); - runOnlyForDeploymentPostprocessing = 0; + name = "Support Files"; + path = "../Target Support Files/Swiftilities"; + sourceTree = ""; }; - 61061657344704E38C1BE0A1EC44A71E /* Headers */ = { + A8D54C77C0BEB46D88F469145C20DE6C /* Frameworks */ = { + isa = PBXGroup; + children = ( + B7010FC71D49408694A41D0B4A22E831 /* AppCenter.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + AAE112D8EBCF66234755E03D80A66A35 /* Fabric */ = { + isa = PBXGroup; + children = ( + C3C63D9CD07021084D0B9C31ED0A87AA /* FABAttributes.h */, + 935548E336DB715970FA91771AE5D568 /* Fabric.h */, + 9EC0439B0FC7C4EEE4048EF00565EA88 /* Frameworks */, + E97757579390FAE0C029F4AB98E7459C /* Support Files */, + ); + name = Fabric; + path = Fabric; + sourceTree = ""; + }; + AB4E2AFBBBBF559816C14051C59A22D0 /* BetterButton */ = { + isa = PBXGroup; + children = ( + E6B719E9A14C1E430887BE3B805CDDE2 /* BetterButton.swift */, + ); + name = BetterButton; + sourceTree = ""; + }; + AE6F222D95639EFAB3F51992DA3BAEB5 /* Anchorage */ = { + isa = PBXGroup; + children = ( + 13FC2F155F0438B5C95978061F39743F /* Anchorage.swift */, + 2F6E205211513A677E520BAD5BD8C183 /* AnchorGroupProvider.swift */, + CF22CC9C8607DFE61523790B4E8080FC /* Compatability.swift */, + 2CA2C241BE9B8942C2622A8288159183 /* Internal.swift */, + 5D2F76C4975A9F75ECFED7459246BDCE /* NSLayoutAnchor+MultiplierConstraints.swift */, + 968AD6C6067177F3FFBF4E22B5D62AFA /* Priority.swift */, + ECC016BE841E69D8F7164C18E603AB7D /* Support Files */, + ); + name = Anchorage; + path = Anchorage; + sourceTree = ""; + }; + B51FA2DAB550422A08450335F068110D /* Swift */ = { + isa = PBXGroup; + children = ( + 00D5703DE6D32E8BEE77AC1C2A64D12F /* OHHTTPStubsSwift.swift */, + ); + name = Swift; + sourceTree = ""; + }; + B73AC685A73B7CABCDF13699741B1462 /* Support Files */ = { + isa = PBXGroup; + children = ( + D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleAppMeasurement"; + sourceTree = ""; + }; + B7C8A5E2542B08353007D5D146E3951A /* NSURLSession */ = { + isa = PBXGroup; + children = ( + 92B3A83AF7CBD24CFB27352A8A473464 /* NSURLRequest+HTTPBodyTesting.h */, + FB31D468DB67CC3C68E932FF60724283 /* NSURLRequest+HTTPBodyTesting.m */, + F2181E7978D4D5EB57672242678285CA /* OHHTTPStubs+NSURLSessionConfiguration.m */, + DA1CB779343A19D8C026EA3A9FD492D0 /* OHHTTPStubsMethodSwizzling.h */, + B0DF923FAF38D4B7E93295F4F7B7E252 /* OHHTTPStubsMethodSwizzling.m */, + ); + name = NSURLSession; + sourceTree = ""; + }; + BC59AFE25F73D0ABD159E379B3DA14B5 /* Alamofire */ = { + isa = PBXGroup; + children = ( + 3D6B1D921CE2EF324C684690E9B44CD4 /* AFError.swift */, + 5D79D6EFCA519A3D859AD623DEEA3E97 /* Alamofire.swift */, + 773F43FA50FABF1CE0C562282F32D624 /* DispatchQueue+Alamofire.swift */, + 3CFCAB771CD0ED282F14A09984871047 /* MultipartFormData.swift */, + B11A4E7961F768D0892E18D1649C5FE4 /* NetworkReachabilityManager.swift */, + 26820BF7BDA3D0A1D104CE81E2CF5EEE /* Notifications.swift */, + 367EF090BA9D626CCBE6C72374BAB47B /* ParameterEncoding.swift */, + D362F402CE5684297570016D7825F239 /* Request.swift */, + 0AD7A8A7135C2FC81974892005E66656 /* Response.swift */, + A23C1F66FE104A9AB25DB49ABA41F52E /* ResponseSerialization.swift */, + 45D7EE49F14DA03DC27AA4631DE48483 /* Result.swift */, + 62F4647B8C0D1352B1C58A2CCAC8F8A1 /* ServerTrustPolicy.swift */, + 1248BFF6EDD2B0B1963D8E18335E0DCD /* SessionDelegate.swift */, + C0CD839E48FC413F0F119BC2DF2B9FF2 /* SessionManager.swift */, + 548F85D6FB2D9B296B3CB2FD0B313CDC /* TaskDelegate.swift */, + 0613D7FC4E5B1B63B0C08F9883F7B6CB /* Timeline.swift */, + DCF0EDF0E175A8ABAE1DC6C2A8C67270 /* Validation.swift */, + 4B759243E3FC5DFD9399CEDDF79EB5AD /* Support Files */, + ); + name = Alamofire; + path = Alamofire; + sourceTree = ""; + }; + BE2E0F88645A73CD5BA9E99C1452EAEE /* FormattedTextField */ = { + isa = PBXGroup; + children = ( + 2F85F03D3204EDFA79866F18C991616C /* FormattedTextField.swift */, + ); + name = FormattedTextField; + sourceTree = ""; + }; + C27D89BC0C94CADF409F60D4FB950035 /* Lifecycle */ = { + isa = PBXGroup; + children = ( + EA144693E6BF8FE7CAC6E965241CE03D /* DefaultBehaviors.swift */, + 5D1F592A03F29834A482A527C26C43F1 /* LifecycleBehaviorViewController.swift */, + 441C8E5411061099355CF78039DCB16A /* NavBarHairlineFadeBehavior.swift */, + 01502087710687B101E4DBC35B149B69 /* NavTitleTransitionBehavior.swift */, + BCDA99AA3900C0A75CF6AFE7E2BEF2A0 /* UIViewController+Lifecycle.swift */, + 0D70F6C27F2262A020CDFA6DBA6E0A95 /* ViewControllerLifecycleBehavior.swift */, + ); + name = Lifecycle; + sourceTree = ""; + }; + C437B8DB3B41FE0E5ACEAF497FD4A0AF /* Products */ = { + isa = PBXGroup; + children = ( + 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */, + B477F169CB917A9F07ABB3C6B0ED46BE /* Anchorage.framework */, + 11AF731E4071DCD5E34B4CA294302B92 /* AppCenterDistributeResources.bundle */, + 33A4868B2CB72C28A43C9793FA150418 /* BonMot.framework */, + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */, + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */, + 5B654B4B042BA7DC93766943A643E42B /* FirebaseMessaging.framework */, + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */, + E8EE7F078656FABB8F6821D10FF994BB /* KeychainAccess.framework */, + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */, + 17E33041B314FA837A3CAEB9DF3CDE9F /* OHHTTPStubs.framework */, + 3C43A20C9129EB73F5BA4F3C40D9A27A /* Pods_PRODUCTNAME.framework */, + 8B0B7D7F03E7C5408A9FEDE21398424D /* Pods_PRODUCTNAME_PRODUCTNAMETests.framework */, + 029DC932573FD3CFF2AB08725C770343 /* Pods_Services.framework */, + C2105C94812B6214B154F54DCEDB72AC /* Protobuf.framework */, + A787CDE742CEB6FDF5F73F556D790691 /* SimulatorStatusMagic.framework */, + F7696B90A3B3D1C34C7E852254DD74F1 /* Swiftilities.framework */, + ); + name = Products; + sourceTree = ""; + }; + C59A82E1D6A01A9AEE70D0221E9593F7 /* Instabug */ = { + isa = PBXGroup; + children = ( + DE16395C09D232F30431F9810A0872D2 /* IBGBugReporting.h */, + 5EB40E5CF6D5BE4269E687E374531BA9 /* IBGChats.h */, + 1B6C4D3F28F3CBA7CF305CB592F85E32 /* IBGCrashReporting.h */, + 82350E48404736EC458CE6073EFD26C3 /* IBGFeatureRequests.h */, + 71A5AB122315590AD0A59A0DA56F3DA9 /* IBGLog.h */, + 488D7FCF0C4C3011E9931E973C97CB62 /* IBGNetworkLogger.h */, + CB5E05211C1CC74484FAD2D8B97F2437 /* IBGReplies.h */, + D3CAB6FE3C8CDCA5DBD77435EA5A937D /* IBGReport.h */, + A0540CA217C994053589CECC283EFEE1 /* IBGSurvey.h */, + 4FC53E880281E6082EF5E821D70B924D /* IBGSurveys.h */, + 179351A254DB884FEB79BA11A69753BF /* IBGTypes.h */, + 79B0EA6DE3F64B8EB2ED292B450C2FBB /* Instabug.h */, + ED06C07D733F97DE5A5F19FEBD086CF5 /* InstabugCore.h */, + 0B7FB0654F18D64FE0D7A2EAAC682B23 /* UIView+Instabug.h */, + E60F7906D799BBA108A0DAB4D2153C5B /* Frameworks */, + 61E1FBD62BF31EF9C5C6FCF8C2475554 /* Support Files */, + ); + name = Instabug; + path = Instabug; + sourceTree = ""; + }; + CA9B7F5CACE5568B170B81CEF9190D72 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 7F7F3C5E8428F9EC082EB77C8B6C0743 /* Pods-PRODUCTNAME */, + 8BDFEEE65FACF169A2EB85AE06AD1146 /* Pods-PRODUCTNAME-PRODUCTNAMETests */, + 7A06EBF1D3AE62AED0DC085715332089 /* Pods-Services */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + CEC3374FD169D13C3E074C43021D181B /* NSData+zlib */ = { + isa = PBXGroup; + children = ( + 966E61D7CDD4B8F269B4C52F6C9D4E6F /* GULNSData+zlib.h */, + E73E251E3CF96E1495BE3EC085526D94 /* GULNSData+zlib.m */, + ); + name = "NSData+zlib"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 8275CCB4E8732497B1021FCBC240F3C2 /* Frameworks */, + 8D527B9C3DE0F3C4790F2C72704D59DC /* Pods */, + C437B8DB3B41FE0E5ACEAF497FD4A0AF /* Products */, + CA9B7F5CACE5568B170B81CEF9190D72 /* Targets Support Files */, + ); + sourceTree = ""; + }; + D5A1FC161D50AE992042E65485320E60 /* FirebaseCore */ = { + isa = PBXGroup; + children = ( + 1A2C2A90AABD3780C5969C4B208AF34F /* FIRAnalyticsConfiguration.h */, + 5FBA28A120B7A31F4D7E17E23F881916 /* FIRAnalyticsConfiguration.m */, + F6D1E9800DF9216163D243A25E5A7E22 /* FIRApp.h */, + 137550D164A3DC3110CE137D5BC383BE /* FIRApp.m */, + F0821896A90AE916F84B3E580249644D /* FIRAppAssociationRegistration.h */, + 0245E1DD96C5A71E0976E257585FB875 /* FIRAppAssociationRegistration.m */, + E893CE5D8A792CBF4C835E33C903AB37 /* FIRAppInternal.h */, + A9F6CAA436B21A9F893735228C041394 /* FIRBundleUtil.h */, + 367F00084F5782810F06E3AE60988239 /* FIRBundleUtil.m */, + CE3DE9896DF364A9A8E70FBF3411CAAD /* FIRComponent.h */, + 900494C92D1BC8DD44B41A1E185446A2 /* FIRComponent.m */, + 72AA8EF20A9E0ED207B17A82A67948D7 /* FIRComponentContainer.h */, + 5CF43C772DF570A45DC9831438386FF8 /* FIRComponentContainer.m */, + 4E4A10F6099BBA9290EDF1F50E4E1E06 /* FIRComponentContainerInternal.h */, + 994790A4BDFB35C5FEEEB4B16ACD0073 /* FIRComponentType.h */, + 990D5BCA382BD9D9D2C3C1E291F2B135 /* FIRComponentType.m */, + B5391DB5CF7FE004619D4F1920521EA2 /* FIRConfiguration.h */, + 9B7024F62947EF6E2C6FB6CD5B34E2ED /* FIRConfiguration.m */, + 106E91C219A27E966E2F6168D1D7F3CA /* FIRConfigurationInternal.h */, + 3D735903962EFF3FC6A7517312F923CA /* FIRDependency.h */, + FF710E85F020077130E558211B5B8D8A /* FIRDependency.m */, + CEC8FF8EB54F243F318CF7B7F16F7278 /* FirebaseCore.h */, + 86B9F61513C3569FB8F5F80587BD0802 /* FIRErrorCode.h */, + 78082F41A23883083EE4061BFC18A4D3 /* FIRErrors.h */, + AC024504A5C4B47AE13B434EA483D427 /* FIRErrors.m */, + 4B4AA562F866C56D8D686538218F79EA /* FIRLibrary.h */, + 5C494458D65556B106276B45877C5407 /* FIRLogger.h */, + 7902953F39F914B13DAD07D6C494973D /* FIRLogger.m */, + B02CBEEE2EAAE48F5C59A0748E149382 /* FIRLoggerLevel.h */, + D2B4AA2B21255F7A6AA09F0E059321BF /* FIROptions.h */, + 97EFF3947D869F0FC7D7D08A1B3B0A6E /* FIROptions.m */, + 4FC123B26387B1A38B1AAB531554C64E /* FIROptionsInternal.h */, + D436B935FFA96DDB042376CB5C11E29E /* FIRVersion.h */, + 772EBD4355380FAEEEE486F50277CA1F /* FIRVersion.m */, + 662F353757E6B7E31DA01A696E1A2E2C /* Support Files */, + ); + name = FirebaseCore; + path = FirebaseCore; + sourceTree = ""; + }; + E09CF835A9CE9B38B033D04BE754B8C6 /* LicenseFormatter */ = { + isa = PBXGroup; + children = ( + 1B77C6FBEB46883FCDBBBF0333AAA959 /* LicenseFormatter.swift */, + ); + name = LicenseFormatter; + sourceTree = ""; + }; + E101FC07342B02BB434763AB5503FDF0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 45FA4D2E7421B8D456A7B6F36884B54B /* GoogleAppMeasurement.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E60F7906D799BBA108A0DAB4D2153C5B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0FF31F44B7641D6494DCF4BD9B15D1D2 /* Instabug.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E81AD734C1E0D7D9E60EBB121AB226B1 /* Support Files */ = { + isa = PBXGroup; + children = ( + FCCFBDA197465FE364E665276C2A88CA /* FirebaseInstanceID.modulemap */, + A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */, + 8FD395C6B080D05AA0E9B521C84DE95C /* FirebaseInstanceID-dummy.m */, + 72C7D6029AC9F37ABD0F2A4F076D6125 /* FirebaseInstanceID-Info.plist */, + A86060F6B97532F283FE392A2B356F3F /* FirebaseInstanceID-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstanceID"; + sourceTree = ""; + }; + E97757579390FAE0C029F4AB98E7459C /* Support Files */ = { + isa = PBXGroup; + children = ( + E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Fabric"; + sourceTree = ""; + }; + ECC016BE841E69D8F7164C18E603AB7D /* Support Files */ = { + isa = PBXGroup; + children = ( + FD757FD2EC6B3B19A20C755C1B166C5C /* Anchorage.modulemap */, + 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */, + 569222352AED8AA275E1295F319C179D /* Anchorage-dummy.m */, + 86773016D7292DB1077AB6ED22B7CAE1 /* Anchorage-Info.plist */, + 4EC0877FA9D2F6B5649644D06256D79A /* Anchorage-prefix.pch */, + 031FC7BA2605BE0368D9692DBDC15D81 /* Anchorage-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Anchorage"; + sourceTree = ""; + }; + F04C2CDACCB32D83923281C298391F52 /* Logging */ = { + isa = PBXGroup; + children = ( + 7A99BF2E906BA57B9D716EC2F28447CF /* Log.swift */, + ); + name = Logging; + sourceTree = ""; + }; + F207982E6DE213CFE74F9EF7393F63A1 /* RootViewController */ = { + isa = PBXGroup; + children = ( + DD6A6E8BEA17526E69B7E7C440D290E2 /* UIWindow+RootViewController.swift */, + ); + name = RootViewController; + sourceTree = ""; + }; + F52DE65EA93C92C1F1F94D5B0BC29E6A /* Reachability */ = { + isa = PBXGroup; + children = ( + 14E3AE25C553C268ECABA7BA60383152 /* GULReachabilityChecker.h */, + B2E98DDB0684CD0EED258207851A2A13 /* GULReachabilityChecker.m */, + EFBAAB841881AAAD3B071BA31361B288 /* GULReachabilityChecker+Internal.h */, + 73B6B0B82C4B090FD5CCE3E4B3185607 /* GULReachabilityMessageCode.h */, + ); + name = Reachability; + sourceTree = ""; + }; + F7114582B168E212D19780C5CCFBEC19 /* Support Files */ = { + isa = PBXGroup; + children = ( + 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalytics"; + sourceTree = ""; + }; + FBB07FC05F11C073D5B30FFFF4FB1787 /* decode */ = { + isa = PBXGroup; + children = ( + ); + name = decode; + sourceTree = ""; + }; + FC97710BA2AAAA3C677BBC481F15EDAE /* Views */ = { + isa = PBXGroup; + children = ( + AD145FCE40536EC56F550EF22AE3A2B3 /* GradientView.swift */, + 59995D0C9E351E7C567DF118C940304B /* PlaceholderTextView.swift */, + 0ED0360339FFD929C312164430AECEF5 /* Protocols.swift */, + 4F7DFC7F79DE29AD380D6C23EF374F66 /* TailoredSwiftTextView.swift */, + 2765A7D6EF27B9AB42D6279A14D1669A /* UITextView+Extensions.swift */, + ); + name = Views; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 03049833CA31385BB30D4A6974B16E79 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C9D3548AB6302BFF4E52AB249E9B2FA /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0431DD53A227464D09A063063050448A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B501012C85EBF16411A4B9CF856A3044 /* BonMot-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1E515CC83C1A6C69B90E75E32C99344A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C289B85A33500EE2453F08CE5D0DB7EC /* GoogleUtilities-umbrella.h in Headers */, + B075936A698C95B193BF870AF0C5DE9C /* GULAppDelegateSwizzler.h in Headers */, + 05A179D28D1AEFB2994F50DF04732ECC /* GULAppDelegateSwizzler_Private.h in Headers */, + B070DBBE6F946A656405E140E975A211 /* GULAppEnvironmentUtil.h in Headers */, + 9B713E8E0EFE0EA70A995827E5394683 /* GULLogger.h in Headers */, + 414165239CE300A52CEB93BE48E70607 /* GULLoggerCodes.h in Headers */, + BC256D583C7221D6FE3DC13F08C02FEA /* GULLoggerLevel.h in Headers */, + 63E56D00C55C0A10C4B75F082AF81B6E /* GULMutableDictionary.h in Headers */, + 8D8C7DD544D90026F85550B2CC95CBD5 /* GULNetwork.h in Headers */, + 2E5638B808692AE3B2213A66E618B793 /* GULNetworkConstants.h in Headers */, + 756BA8556D315CD499501E923700528F /* GULNetworkLoggerProtocol.h in Headers */, + A818814179D868596CE5F1BC13302BB3 /* GULNetworkMessageCode.h in Headers */, + 92716A0085066BCCB43369069E76403A /* GULNetworkURLSession.h in Headers */, + 6FA68690945C1A9D56524BE6EEB1B23F /* GULNSData+zlib.h in Headers */, + 0C0BF1B04934ADA346E62844B9324E2A /* GULOriginalIMPConvenienceMacros.h in Headers */, + B4B77955EC2C522E041EBA397F87FE65 /* GULReachabilityChecker+Internal.h in Headers */, + 8FBBD77BDF34DDAA858E757318F1FAC5 /* GULReachabilityChecker.h in Headers */, + AA2AA7707B86A60F4E9CCA3E1BE504CA /* GULReachabilityMessageCode.h in Headers */, + 816CD4237A652BDEADE317F1DD341A0E /* GULSwizzler.h in Headers */, + CBBFF56D23D20E974E5D8DF04EF3637B /* GULUserDefaults.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 31917A544DEDF75840A86242DA086C54 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 09BBB2DFD0CCA4F842ED217E1ADE6141 /* nanopb-umbrella.h in Headers */, + 05EBDF811901C96CB4A388C239C95E5C /* pb.h in Headers */, + 67D67C17FCCB5F83FF620BD048630184 /* pb_common.h in Headers */, + CA260A0E0878CEE776DE12492DF46949 /* pb_decode.h in Headers */, + DFADB7B9266D1032D5BF21F2F1D02D96 /* pb_encode.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51047DA7E35C429BC28F0F43004BD8C2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FC6AFA3387CA425C566B007F0EA9B9A9 /* FirebaseMessaging-umbrella.h in Headers */, + 988E2668D29D51B8304BC24235BA15B6 /* FirebaseMessaging.h in Headers */, + 9811AF1663228E41A0F9116F3FDAB4D3 /* FirebaseMessaging.h in Headers */, + 93B158CFAE0146108F8D3DF1F5DF2FEE /* FIRMessaging.h in Headers */, + 059037195C74C676763DE7253C64DCAC /* FIRMessaging_Private.h in Headers */, + 9C27962A6C09FD001BE83B3873C40856 /* FIRMessagingAnalytics.h in Headers */, + 03EF25966CA31FFBC31B8044BBDB7C78 /* FIRMessagingCheckinService.h in Headers */, + 66F6BC937ACA5E47AF09DB8ABB6D7645 /* FIRMessagingClient.h in Headers */, + 2BC2424190D3B6288B51C3DAAC70FE0D /* FIRMessagingCodedInputStream.h in Headers */, + 5066B89BFDEBC3087F0077E0E19D605A /* FIRMessagingConnection.h in Headers */, + D46809D86D5BB4EBB9AA10F29979A860 /* FIRMessagingConstants.h in Headers */, + 6AC487E61CBA42325EAEE431BBCCA6C0 /* FIRMessagingContextManagerService.h in Headers */, + 6AA8F0D7888C5B32C0D72865D646F69B /* FIRMessagingDataMessageManager.h in Headers */, + 94F0EFD969D064F5D663A6EE835D4516 /* FIRMessagingDefines.h in Headers */, + 989554E915C48AB0868348384AE545C8 /* FIRMessagingDelayedMessageQueue.h in Headers */, + 7EAB3629AFCDDB950B9A4C610588D97A /* FIRMessagingExtensionHelper.h in Headers */, + 27A8DB4EE609E1FABE7EA7835B6FF28B /* FIRMessagingInternalUtilities.h in Headers */, + 8D769B1E75C52E3BFAC64ABA8CA438FE /* FIRMessagingLogger.h in Headers */, + E98CBA7CFCF3D96C5B50770A4D3517B5 /* FIRMessagingPacketQueue.h in Headers */, + 220FF13741674D3D3CF5BAD8DFCE5E92 /* FIRMessagingPendingTopicsList.h in Headers */, + BA0C33AE7563904D128CB643510CCBE3 /* FIRMessagingPersistentSyncMessage.h in Headers */, + 17CA76C0BACF692C96BD0A789D76C08D /* FIRMessagingPubSub.h in Headers */, + 8A8D4BB3B21FE7CECDAA6908E6886531 /* FIRMessagingPubSubRegistrar.h in Headers */, + B8C5257CFBE55442EECF051DF82E729B /* FIRMessagingReceiver.h in Headers */, + 96468709B156DCAC50DABCA9CB197F21 /* FIRMessagingRegistrar.h in Headers */, + E985433DB346442DDCB5F6E16CE7D280 /* FIRMessagingRemoteNotificationsProxy.h in Headers */, + 2AA0A2B7267E8E75525D003D9A96E6ED /* FIRMessagingRmq2PersistentStore.h in Headers */, + 9C24AF3D249563A26F59EDFBA4C7773A /* FIRMessagingRmqManager.h in Headers */, + 0D110E5F8DB3A38046128C3AD51467AC /* FIRMessagingSecureSocket.h in Headers */, + A18D4637F3EB0E9D08ABB14CE34737CF /* FIRMessagingSyncMessageManager.h in Headers */, + C9157A5A1365EB4A1D49EC2E8619E4F7 /* FIRMessagingTopicOperation.h in Headers */, + 23A2410F3C4DE63B77014C9DE596F51C /* FIRMessagingTopicsCommon.h in Headers */, + 71775A89A3802A1BA58BF1BB41DDD9A1 /* FIRMessagingUtilities.h in Headers */, + C19BF82AAEAC7AD417C728F4C00B58CE /* FIRMessagingVersionUtilities.h in Headers */, + 021DB76932CE50DD90304FEBFCA8BE77 /* FIRMMessageCode.h in Headers */, + EF6D8F4A474E5287ABFAE4449F45C827 /* GtalkCore.pbobjc.h in Headers */, + F751BBA11B2C9DB683D3FAC54D1B54EC /* GtalkExtensions.pbobjc.h in Headers */, + BBE95066A8DC1C8D8CC907000D70541A /* NSDictionary+FIRMessaging.h in Headers */, + C329C3A3A838C4AD86611F67A10BFEAF /* NSError+FIRMessaging.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5ACB9E7F9554486F77804743DD21C9FF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 307995802DBDCAE24CD40AA467DFDD9D /* Swiftilities-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 70969CE00B19E6C2CA2868F9FA0AE35C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A3492135E0BFF1F6BE2DB3BCB52907C7 /* KeychainAccess-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8823DEEADB239F8D563D480A7126611F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A81ADD3C0C26EEFD1409AD35142E0AF /* Pods-Services-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8F23573CF45EC7A6EE1BEBC0F3BA4606 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - C883489560D63778318E2FD860326389 /* Compatibility.h in Headers */, - 36C99CC230B66FCBE3873860A22742F9 /* NSURLRequest+HTTPBodyTesting.h in Headers */, - 2D80427789ACD436DB938223E2268014 /* OHHTTPStubs-umbrella.h in Headers */, - DC806AF439B1AB8881B705058EEDEC16 /* OHHTTPStubs.h in Headers */, - 4CA5BFEEC04C9A430BD5E4F74C7F555A /* OHHTTPStubsMethodSwizzling.h in Headers */, - 8CD59949C6FC86186476CE9430AD6E3C /* OHHTTPStubsResponse+JSON.h in Headers */, - 5655EFB774E324469A09273B1512314D /* OHHTTPStubsResponse.h in Headers */, - 6A6A63FFC93F55AC483492B8FFEAC07E /* OHPathHelpers.h in Headers */, + D448F684FAE5EF02A10E467A097B2B8E /* Any.pbobjc.h in Headers */, + D86369D98CDF2CD116CBC4B66B089CEB /* Api.pbobjc.h in Headers */, + 807B6E3FF4C4A97577F4D5EDDDD49ECC /* Duration.pbobjc.h in Headers */, + 7C9F9297EAC2E0A5302B50564B575B0A /* Empty.pbobjc.h in Headers */, + 4BAB4E1DF3D4D6AF88A8508E3A2F09A8 /* FieldMask.pbobjc.h in Headers */, + 68333497E7CEB0B383B8F14BF0B0B6BE /* GPBArray.h in Headers */, + 93FEDE6C16994FA82F27CC56168013FF /* GPBArray_PackagePrivate.h in Headers */, + 0AAA11C4CFB301157A24BF56A7C1ED7E /* GPBBootstrap.h in Headers */, + CE60B4B85D17A08CA721EEE416CD1C83 /* GPBCodedInputStream.h in Headers */, + 488F9DFC7A23F9EA87DA50076865695A /* GPBCodedInputStream_PackagePrivate.h in Headers */, + B9AFBB66C67E71F0BFDD0DE5687C9CBC /* GPBCodedOutputStream.h in Headers */, + 1BE02480F93F6FEF703BC98F779A8FBE /* GPBCodedOutputStream_PackagePrivate.h in Headers */, + 50A0609DC011B95A498F342D6A496297 /* GPBDescriptor.h in Headers */, + BE2C9A27C741D9C0773B4037E0D68B57 /* GPBDescriptor_PackagePrivate.h in Headers */, + 365196A7B4EE1C83C432D345AA839C88 /* GPBDictionary.h in Headers */, + B6D9136FE482A5716B99CAE6FF7545F4 /* GPBDictionary_PackagePrivate.h in Headers */, + B734B64212F2A039FCAC85F14608AACA /* GPBExtensionInternals.h in Headers */, + F2C4A6F7AC480DEFAE6217C46C05E974 /* GPBExtensionRegistry.h in Headers */, + 890D4B46D1BE3870CA15607A41327FAF /* GPBMessage.h in Headers */, + 643932FF6C60A7B50E69281BEC283DCC /* GPBMessage_PackagePrivate.h in Headers */, + EA4C0FEE83B95FA4CBD6A1C7A1041CCA /* GPBProtocolBuffers.h in Headers */, + 3F318A17631E107812E804B75FFB7FA6 /* GPBProtocolBuffers_RuntimeSupport.h in Headers */, + E75E3A02BC9CCB56D1671F7FDCB1D543 /* GPBRootObject.h in Headers */, + 1B9376E58DD7B9226E8EBA79391DF110 /* GPBRootObject_PackagePrivate.h in Headers */, + 5D6901CB7E479AF1C5F8A340BABB727A /* GPBRuntimeTypes.h in Headers */, + 93F97DB70699CDB8C433DEB03991621E /* GPBUnknownField.h in Headers */, + 36D435F6F2D69F1A933BAE5D27B0EF85 /* GPBUnknownField_PackagePrivate.h in Headers */, + 35E679A58A9EF087D8AAFB484914B64E /* GPBUnknownFieldSet.h in Headers */, + 8060AA86BCD21633E21A8DA29FD56D07 /* GPBUnknownFieldSet_PackagePrivate.h in Headers */, + 1E84D4A521B67526F319DBFFCE9486B7 /* GPBUtilities.h in Headers */, + 8C435621C8561A336FCB112215CE7F06 /* GPBUtilities_PackagePrivate.h in Headers */, + 33108ECB357D1206B36ED2F85AC12269 /* GPBWellKnownTypes.h in Headers */, + 760970F7357E9ECCDFF141830982057F /* GPBWireFormat.h in Headers */, + 74CFDB81D12600FF74EAF4FE27423E07 /* Protobuf-umbrella.h in Headers */, + 5F12EFB41C6F7259375BF3E842CE980A /* SourceContext.pbobjc.h in Headers */, + 7F665E687CD8C311206F990CD0DA7418 /* Struct.pbobjc.h in Headers */, + FF1D8B1CA0865B7484F0874C6517D3CD /* Timestamp.pbobjc.h in Headers */, + 1A0898925095DFC70512C1A28BD9F587 /* Type.pbobjc.h in Headers */, + BF4C76B8E0C15E7C2A4762EBB84872F0 /* Wrappers.pbobjc.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - A9765635F39133BD41CCD8488491A010 /* Headers */ = { + B8851F99376F0F8A8D9CEE158F4A4DF5 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 7EB9B575E1B2B22C9D11A03AEEF214C4 /* Pods-PRODUCTNAME-PRODUCTNAMETests-umbrella.h in Headers */, + 6A9ACBEB61712282B87B0A3090045B36 /* FirebaseInstanceID-umbrella.h in Headers */, + A7A6BF0C62BC3FC2F757468C317099EE /* FirebaseInstanceID.h in Headers */, + 9895E36F7164AEA6EFADE585598C4B9F /* FIRIMessageCode.h in Headers */, + BEC7476DE1CF263A31FA893D2B2A2E70 /* FIRInstanceID+Private.h in Headers */, + 917E9C7AF939B0FFD3C026BB4EAC73DF /* FIRInstanceID.h in Headers */, + F5A597E46D8296D2C414626E7F99C0EF /* FIRInstanceID_Private.h in Headers */, + 9243AFCD79CC422AC3AE16E6CB0C262D /* FIRInstanceIDAPNSInfo.h in Headers */, + 83CA30B037DEB0527448F9C54F396B2E /* FIRInstanceIDAuthKeyChain.h in Headers */, + 28501C3F19644C8E8888E168B5163A2B /* FIRInstanceIDAuthService.h in Headers */, + 949E82C19D7A44BEA21AE96476C2E533 /* FIRInstanceIDBackupExcludedPlist.h in Headers */, + F9A8B355EC256F8B149021EB7C0F8998 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */, + A3A7C1C339F3BDCF7DAE115107D4FC89 /* FIRInstanceIDCheckinPreferences.h in Headers */, + CE8F8AFEE45337F90EBA0EB35A82939E /* FIRInstanceIDCheckinPreferences_Private.h in Headers */, + 130BCF85E0BDD69B046F3000354BA0B1 /* FIRInstanceIDCheckinService.h in Headers */, + 07004386F300F8DD87A2D100C010521B /* FIRInstanceIDCheckinStore.h in Headers */, + 409D2E6AB1246D3B41550EC6F8B68695 /* FIRInstanceIDCombinedHandler.h in Headers */, + 6A5EF7BFD9E1F744141F8FADA93CC40C /* FIRInstanceIDConstants.h in Headers */, + E88203FD8E2B01EB71219367D94608D0 /* FIRInstanceIDDefines.h in Headers */, + 26939CAD52ABAD1A55806F176550DA26 /* FIRInstanceIDKeychain.h in Headers */, + 49D4D750DDF02487C8AA4B26B1D85942 /* FIRInstanceIDKeyPair.h in Headers */, + B39604A46A4903C262D18E317F1E6C6C /* FIRInstanceIDKeyPairStore.h in Headers */, + 49894777E431600670C3413CFD08CBAC /* FIRInstanceIDKeyPairUtilities.h in Headers */, + A5F185E6FD5C3BBCF46BF62774965E31 /* FIRInstanceIDLogger.h in Headers */, + F5DC2F62DE6E7D1D2166347768660F62 /* FIRInstanceIDStore.h in Headers */, + E1797B933E4A716E831F34EFC24F2A18 /* FIRInstanceIDStringEncoding.h in Headers */, + BFD1F6C176B28F48CCF2BA6577A6C170 /* FIRInstanceIDTokenDeleteOperation.h in Headers */, + 7D9390DFB58EAEF71DA1CE4E5F4AA98D /* FIRInstanceIDTokenFetchOperation.h in Headers */, + 2B088D091DA7DA702E17C2022DFE2D14 /* FIRInstanceIDTokenInfo.h in Headers */, + 8DB74A47E65D6DF7F9632EA8709028C7 /* FIRInstanceIDTokenManager.h in Headers */, + 837BDD2C7B095A5B3544B3B632ADA738 /* FIRInstanceIDTokenOperation+Private.h in Headers */, + E86C0147FE8704C88040B0AFEF4E7648 /* FIRInstanceIDTokenOperation.h in Headers */, + AAA60349DF99530BA4F476C8D9DF2AC7 /* FIRInstanceIDTokenStore.h in Headers */, + DC5DA57E4485C2FC85FDF53428C747DF /* FIRInstanceIDURLQueryItem.h in Headers */, + 1168EAF844C5167A969F992B39124E95 /* FIRInstanceIDUtilities.h in Headers */, + 93FE3279105620965FABBD2F6D30ADB1 /* FIRInstanceIDVersionUtilities.h in Headers */, + EFE7887C3624E7E6BA06AECB489778FE /* NSError+FIRInstanceID.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - AEBEE836F7EA114E7AF57521F06E3BF0 /* Headers */ = { + BC611EA94FEA3BF8D61D449B9247327D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 0BFC7647D9C51B1E74751697F1CD06C5 /* SDStatusBarManager.h in Headers */, - D831E4DF2BCFDC9ACF0E15A1FE4366AC /* SDStatusBarOverrider.h in Headers */, - 0E793EBB5C54DBCA6680965E88D45D83 /* SDStatusBarOverriderPost10_0.h in Headers */, - 23102CFEC4388DD74DA5B4EC0A55681E /* SDStatusBarOverriderPost10_3.h in Headers */, - E0AAFD9138FBBC64CA5E5D1DB1448FD7 /* SDStatusBarOverriderPost11_0.h in Headers */, - 749AF41B7BBF16638E09E26348C7282E /* SDStatusBarOverriderPost12_0.h in Headers */, - C8A9F97A0CFBE7C804E7D5525954E6B1 /* SDStatusBarOverriderPost8_3.h in Headers */, - 65D81884C107EC21BBB727B057A9600F /* SDStatusBarOverriderPost9_0.h in Headers */, - A43B18898AA1BF4CEA7C52BE9422547E /* SDStatusBarOverriderPost9_3.h in Headers */, - 2593D80AA46FBA1605886C6122935880 /* SDStatusBarOverriderPre8_3.h in Headers */, - 163787FC8590421DC1AAA972E17D7C07 /* SimulatorStatusMagic-umbrella.h in Headers */, + 8F7F70BA374635820D060762A15931D3 /* SDStatusBarManager.h in Headers */, + 3B17099ADDBF828A11994064917317EC /* SDStatusBarOverrider.h in Headers */, + A142ABBB6E27723CB76393007499BBCC /* SDStatusBarOverriderPost10_0.h in Headers */, + E2E71589715B273DE6163D5FB435592C /* SDStatusBarOverriderPost10_3.h in Headers */, + 1BCC66B692E9EDE5C903B4469B4BCE57 /* SDStatusBarOverriderPost11_0.h in Headers */, + 9DD886828EFFBBDB2439ED4B11CE081B /* SDStatusBarOverriderPost12_0.h in Headers */, + B45A8A82A0FD4C548C6DB743E8095E86 /* SDStatusBarOverriderPost8_3.h in Headers */, + 4FC8500AC1BDC6610782C5C287EAFB46 /* SDStatusBarOverriderPost9_0.h in Headers */, + 9335522C7018277CE54C18E182A5A1F4 /* SDStatusBarOverriderPost9_3.h in Headers */, + CA601EE9EDA47E65195D3BF43930A270 /* SDStatusBarOverriderPre8_3.h in Headers */, + 66EF408EFC3D695477CAAA86191FF5A2 /* SimulatorStatusMagic-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - BAB7389A3DA8E1C9FB8F484A8178E13D /* Headers */ = { + CD7D21AA0812F3958596A40163651653 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 902BE41A1CD1EC0BDA233DF4CADB93C1 /* Pods-Services-umbrella.h in Headers */, + D9D8875B70BCDA90E099D5BA8A43A802 /* Compatibility.h in Headers */, + 6239F27D209AFEA6F20DC38D2EA8BF53 /* NSURLRequest+HTTPBodyTesting.h in Headers */, + 8494ADF872F49EA36C4844F0298DD498 /* OHHTTPStubs-umbrella.h in Headers */, + 1011297752537301D863BE2D4B01E43A /* OHHTTPStubs.h in Headers */, + C2158E550AEB96660AD13D089D75543B /* OHHTTPStubsMethodSwizzling.h in Headers */, + CA4CD125AEC29FD189D003762B57494A /* OHHTTPStubsResponse+JSON.h in Headers */, + 9E2AC1BC432B98F9B748D05D7B488CB0 /* OHHTTPStubsResponse.h in Headers */, + 49FF7B5676B99AC5BC66CD274572D5F8 /* OHPathHelpers.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - D57537F8758AF7F234DD7F0645E26309 /* Headers */ = { + DA5283B3D873288E1A36B8278880117D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 12A66D2C67F417928A30B4937F2704C8 /* Alamofire-umbrella.h in Headers */, + F6F184A43AABC119977DF12AD2ED2053 /* Pods-PRODUCTNAME-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - E337C9B0FCDFCD3A627B7F693428029A /* Headers */ = { + E04484D640E829A11EDEA568EB57DB7F /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D0E8FA0DE59D2EAFAEBDA5D0CB9B00F9 /* Pods-PRODUCTNAME-umbrella.h in Headers */, + 94E0EEAC1123DEFF7625B88F0E71E3E9 /* FIRAnalyticsConfiguration.h in Headers */, + 77399B95DEEE5E953DF7BADB4B7139D7 /* FIRApp.h in Headers */, + DA5908E1CF98667FAE1CBEC76D355CA4 /* FIRAppAssociationRegistration.h in Headers */, + 00615AAC8F76F88D5B261CDBAFFC42CC /* FIRAppInternal.h in Headers */, + F9B80E71A9F0D909B1F73CCD753CF53B /* FIRBundleUtil.h in Headers */, + D4EB284204E633D9175B0D5D850EB0EE /* FIRComponent.h in Headers */, + 2DF1DEC33EB066E5581440CD6998386C /* FIRComponentContainer.h in Headers */, + 1C202B0C77A04F7D0E65F399808DBB11 /* FIRComponentContainerInternal.h in Headers */, + 360522FAF4C83FF5BB33C984F4D293B5 /* FIRComponentType.h in Headers */, + 2A06EC8F16F9A176A6E8969AEFCF557E /* FIRConfiguration.h in Headers */, + 4C4E5BAB5F6CEF8DC0184E7045DE6319 /* FIRConfigurationInternal.h in Headers */, + F5770C14010A6EA5DDF6D28111858B75 /* FIRDependency.h in Headers */, + 72E64E250ECE3FED90F8E229980CD42F /* FirebaseCore-umbrella.h in Headers */, + C8A5AA38971136EED1E4BC61205A591B /* FirebaseCore.h in Headers */, + 2B6BD33D9BA13D63533BF7A016186C63 /* FIRErrorCode.h in Headers */, + 23B15157951EFE8223491E517FB38492 /* FIRErrors.h in Headers */, + 55F7228A18EA4ADE7388939284DC1828 /* FIRLibrary.h in Headers */, + 29D8A0E1833835AE95BB8D68783E01D3 /* FIRLogger.h in Headers */, + BEF4756AFAB837E4497F73F05DEDEECC /* FIRLoggerLevel.h in Headers */, + 09F7DF5894417D5165C5B1873E46B448 /* FIROptions.h in Headers */, + 0FD7700F7E5A81A21AEB14558CCCD67B /* FIROptionsInternal.h in Headers */, + 398916FB2E858FCF90B787DF390F0646 /* FIRVersion.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - F0751547A8CBC59641BE57ED6A2B0383 /* Headers */ = { + E1271C58F3B4DED1AC9FAFC325A29CAF /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 0B8D46B2C05CCF70B33086EDCB861DE7 /* Anchorage-umbrella.h in Headers */, + 6C654A56978C6D1886240834580D72C3 /* Alamofire-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - F10AA068344822EA62368C7E24B98361 /* Headers */ = { + E5F63544CC885EFB40146133912498EE /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 9BE56EBC243C1D6202F97AEC29730C84 /* Swiftilities-umbrella.h in Headers */, + A0DD808CD41CE6A758A3C64289598B2F /* Anchorage-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 09CBDA14CEA10182307DD98DDA2F6826 /* Pods-PRODUCTNAME */ = { + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */ = { + isa = PBXNativeTarget; + buildConfigurationList = DEA17664DA1352A9AF015846F7DC4098 /* Build configuration list for PBXNativeTarget "FirebaseCore" */; + buildPhases = ( + E04484D640E829A11EDEA568EB57DB7F /* Headers */, + 8AD0FEC519E2F25A92EFA4A40E97C225 /* Sources */, + 74C2CDA0B2C1E3C0ACC15492B3B38619 /* Frameworks */, + 3D6135916B343D7E548A3F64DBFE6EF8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C4D6DC5312308B518D11684361884474 /* PBXTargetDependency */, + ); + name = FirebaseCore; + productName = FirebaseCore; + productReference = E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 44E83D2F8D3A4919879F6D9FA69CBC61 /* Pods-PRODUCTNAME */ = { isa = PBXNativeTarget; - buildConfigurationList = 8A987AD8034C7D3591A04B28614AB4DD /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME" */; + buildConfigurationList = 4964BEA93FE393CBB81F0EB03B4B3C81 /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME" */; buildPhases = ( - E337C9B0FCDFCD3A627B7F693428029A /* Headers */, - 1E4B59E8391364DDF9098377E471A638 /* Sources */, - 512E07F8CBBE765203C2234921A15779 /* Frameworks */, - 4AEF90BB5E5E75F6CF25F29776072502 /* Resources */, + DA5283B3D873288E1A36B8278880117D /* Headers */, + C5EDC2EFB9F2A36C846524DD554C6A16 /* Sources */, + 726B5C2231D21F110E448BFD5292F6A1 /* Frameworks */, + 88B8A813538905511C304057DC4AC323 /* Resources */, ); buildRules = ( ); dependencies = ( - 56074B1A6858DF2148C6F8AB33AB2B8C /* PBXTargetDependency */, - 7610E8B6599E214698ABF758DE110C52 /* PBXTargetDependency */, - FB72D79D5C32519D1D945170633EEE4D /* PBXTargetDependency */, - EE523C5AA43982C6705936C26BE33556 /* PBXTargetDependency */, - F45F97E2AC9D9901B0B10D817F5D194C /* PBXTargetDependency */, - 9B9AA20443840191F6C4335D9DD7FE12 /* PBXTargetDependency */, - 70EF66862FFA076DC90801BA25B2E000 /* PBXTargetDependency */, - EF971051DAD5EA10088D0143CE95CC26 /* PBXTargetDependency */, - 423CB78AC3BE7CB1E8B3C87FBCAD5DE1 /* PBXTargetDependency */, - 599A74641EEF5EFE5AFC566B1670B92B /* PBXTargetDependency */, - 552F17ED96982496E47F141C3848E90C /* PBXTargetDependency */, - 1EC5FE0850099251D925B46186DF3B25 /* PBXTargetDependency */, - 9201B31C41B3922CD779EC77C152646A /* PBXTargetDependency */, + 4C5E8A7AE78E64723705A8C4F39294C2 /* PBXTargetDependency */, + F0793E63BFABF823AEB6F71A3674DAE1 /* PBXTargetDependency */, + 027A71A52AB8D3D436ECDC9CB733277E /* PBXTargetDependency */, + 76368B6D12BB326EEFA9898C11C103BF /* PBXTargetDependency */, + 790A3D878446B70A5A20256D674AB5E1 /* PBXTargetDependency */, + 72C383DDA0C3B15B45C1BBE8168E7C32 /* PBXTargetDependency */, + 83F2C143D8BEF77B7C4759F0CAFB4E62 /* PBXTargetDependency */, + 9F9E6213111F42F60CF9E3049030C0EC /* PBXTargetDependency */, + FE817F57A0DB193392689548BF3A3052 /* PBXTargetDependency */, + A8FE2505F0526DA98700BDEF778002CA /* PBXTargetDependency */, + 57A98EA8D303A644FA7B50E4295B8171 /* PBXTargetDependency */, + 80661FD0776FF5CE9CEA1E2D72C1B901 /* PBXTargetDependency */, + 5CE6985057CE4B265103CF4F42193E36 /* PBXTargetDependency */, + D26A457C36225DE41C7BB4FD7A7FF254 /* PBXTargetDependency */, + 5C27114E1234A898AE9167984987A6BB /* PBXTargetDependency */, + E4A173EB136AA75485C7DD75F12B1475 /* PBXTargetDependency */, + 517C4D4310C32500D8D3C4AFB217A87A /* PBXTargetDependency */, + 34CC4B4491776D9C45A351FBC15D65D4 /* PBXTargetDependency */, + FE3F8C74A60E5614770271527A3085D9 /* PBXTargetDependency */, + D0405CD352F9BA331E0835E76731E1D5 /* PBXTargetDependency */, + 5F429333A5E8F5B0843B8383C878CEDD /* PBXTargetDependency */, + F7AB0C563506FE1FE6520F4C7180C61E /* PBXTargetDependency */, + FEB053648A54BC05E6A6BD49CB6EFFB8 /* PBXTargetDependency */, ); name = "Pods-PRODUCTNAME"; productName = "Pods-PRODUCTNAME"; - productReference = 5C36B781D279FBC53B84933BBA772A0E /* Pods_PRODUCTNAME.framework */; + productReference = 3C43A20C9129EB73F5BA4F3C40D9A27A /* Pods_PRODUCTNAME.framework */; productType = "com.apple.product-type.framework"; }; - 19F29DF95D2D1863DFA4C4BE96A51134 /* Swiftilities */ = { + 4607A9D579EE69C57F52971930107170 /* Anchorage */ = { isa = PBXNativeTarget; - buildConfigurationList = 27B1D85313010C4465E2E9963174D7DC /* Build configuration list for PBXNativeTarget "Swiftilities" */; + buildConfigurationList = D99A31EFD5DABE8C08BD3F146933A31D /* Build configuration list for PBXNativeTarget "Anchorage" */; buildPhases = ( - F10AA068344822EA62368C7E24B98361 /* Headers */, - 88877C9EE62BF1149861D26290699A35 /* Sources */, - 1B956845D52108B118A34850891255F4 /* Frameworks */, - 35E66FB3BA2F891FCB2B465F10406D39 /* Resources */, + E5F63544CC885EFB40146133912498EE /* Headers */, + B171C95BD079223B02E20B54DAC07B3F /* Sources */, + 32D9EDE9ED3871400CB94EF9184C0D6D /* Frameworks */, + C2335386EAEE724F85DA53C2B57D58AC /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = Swiftilities; - productName = Swiftilities; - productReference = 9AEAE841E281C0D30AD94EEF9FC181AE /* Swiftilities.framework */; + name = Anchorage; + productName = Anchorage; + productReference = B477F169CB917A9F07ABB3C6B0ED46BE /* Anchorage.framework */; productType = "com.apple.product-type.framework"; }; - 2C73C7C87E96DD68B751D61C1033C498 /* BonMot */ = { + 470FE31978DC918618A329D8B55C85FF /* Protobuf */ = { isa = PBXNativeTarget; - buildConfigurationList = F97409124909E20C13076D42CA44F17F /* Build configuration list for PBXNativeTarget "BonMot" */; + buildConfigurationList = 994CC284732864C1FB83DEFEECB2939B /* Build configuration list for PBXNativeTarget "Protobuf" */; buildPhases = ( - 039BBE20CB777B0B7B5E40A54A63D4BB /* Headers */, - 797A737D3C14C77D3201D5096C981EEA /* Sources */, - 70F937D133B19D54060419760D04248B /* Frameworks */, - 5E853518D740022BFFED5A88E6DC21F8 /* Resources */, + 8F23573CF45EC7A6EE1BEBC0F3BA4606 /* Headers */, + 72B8E25E992B707A92C7C56A5B4D1DD0 /* Sources */, + 07E3F9AF597FEC90D3D85283E3E5DA0A /* Frameworks */, + E1E3FEBB4ED67C9E1AF276D80B54F7BA /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = BonMot; - productName = BonMot; - productReference = 96E262BA9A1492BA3FDC9E0786CF277A /* BonMot.framework */; + name = Protobuf; + productName = Protobuf; + productReference = C2105C94812B6214B154F54DCEDB72AC /* Protobuf.framework */; productType = "com.apple.product-type.framework"; }; - 59FF3124354BB8932D3D16CEF7473837 /* SimulatorStatusMagic */ = { + 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */ = { isa = PBXNativeTarget; - buildConfigurationList = 2A5785C21CA61197EDDD1FE2EB0000F6 /* Build configuration list for PBXNativeTarget "SimulatorStatusMagic" */; + buildConfigurationList = EBAF0176DA76634D02397BD80DC087AD /* Build configuration list for PBXNativeTarget "BonMot" */; buildPhases = ( - AEBEE836F7EA114E7AF57521F06E3BF0 /* Headers */, - CE7BA0910603A4A551643819336FEB94 /* Sources */, - 520EE3055734BB8016B7C66C499D04AA /* Frameworks */, - 374A8B88C811B644CB8A05599103D6B8 /* Resources */, + 0431DD53A227464D09A063063050448A /* Headers */, + 29333CABA17205542DF156993C524977 /* Sources */, + 96338CCDB13BC8D010311E35BC765F14 /* Frameworks */, + 64B88C84E52D7233869509EAEC6387F2 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = SimulatorStatusMagic; - productName = SimulatorStatusMagic; - productReference = 5426B4EA8AB7C69CCFB6311BF4008D2F /* SimulatorStatusMagic.framework */; + name = BonMot; + productName = BonMot; + productReference = 33A4868B2CB72C28A43C9793FA150418 /* BonMot.framework */; productType = "com.apple.product-type.framework"; }; - 8D3A1239E052634147734F80F823491B /* Anchorage */ = { + 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */ = { isa = PBXNativeTarget; - buildConfigurationList = 196370951A0DF83F84523C5518D80950 /* Build configuration list for PBXNativeTarget "Anchorage" */; + buildConfigurationList = 7C6BA1361CF9FA39E02D40A29E2613E3 /* Build configuration list for PBXNativeTarget "FirebaseMessaging" */; buildPhases = ( - F0751547A8CBC59641BE57ED6A2B0383 /* Headers */, - 7007F55843F87563D364C9E2E9970D1D /* Sources */, - 62549CEBDEDF5CCF226A2CCD9E564BF6 /* Frameworks */, - 4B4754D0BC19D93992F6BE16833FE0C4 /* Resources */, + 51047DA7E35C429BC28F0F43004BD8C2 /* Headers */, + ECAA69750FA4F99D92214CCBCCDAF45E /* Sources */, + 255C7B5ED5FE9184B51E5BED246FA3DD /* Frameworks */, + 1963B15BA5DDF39E925E404B1B5C69D8 /* Resources */, ); buildRules = ( ); dependencies = ( - ); - name = Anchorage; - productName = Anchorage; - productReference = 96822B1CA2B1F1B51992E9BAD9A99F96 /* Anchorage.framework */; + 509CCF144E767C197328128D373A1367 /* PBXTargetDependency */, + F9A75F4BC4D33D1F83CBE160AE2D088A /* PBXTargetDependency */, + 21126DE93342F0CFC72E8B0BFF74B7C2 /* PBXTargetDependency */, + A3560B04C6C7550C49D3509E4F985634 /* PBXTargetDependency */, + 912865061B33024F53771995A880334E /* PBXTargetDependency */, + ); + name = FirebaseMessaging; + productName = FirebaseMessaging; + productReference = 5B654B4B042BA7DC93766943A643E42B /* FirebaseMessaging.framework */; productType = "com.apple.product-type.framework"; }; - CCAB7541106C9A08F37141B4E6BABE82 /* KeychainAccess */ = { + 615C831BCE925ED486B225B87E44926D /* KeychainAccess */ = { isa = PBXNativeTarget; - buildConfigurationList = 4A64146D9987C769A06B164ECC751636 /* Build configuration list for PBXNativeTarget "KeychainAccess" */; + buildConfigurationList = 99D1947D468DCEAA4431F1F95263DC3A /* Build configuration list for PBXNativeTarget "KeychainAccess" */; buildPhases = ( - 46DA116D0F3AF61E855459946FCE7335 /* Headers */, - 11619895668C05836EE67CE37E612B01 /* Sources */, - D8A62289535A21591BCB588314E6C871 /* Frameworks */, - 464192478BD009031C2F32EDADB8D464 /* Resources */, + 70969CE00B19E6C2CA2868F9FA0AE35C /* Headers */, + 4A702EEC54A13B2F366712E2E1EAB9DA /* Sources */, + 1EAA3BD0F5BEEE46CCBAA84201853CB8 /* Frameworks */, + 51833BAA88321210CC48C9DF8B11D18B /* Resources */, ); buildRules = ( ); @@ -1947,111 +3835,230 @@ ); name = KeychainAccess; productName = KeychainAccess; - productReference = 301105F4D7338338C59D0195933FA755 /* KeychainAccess.framework */; + productReference = E8EE7F078656FABB8F6821D10FF994BB /* KeychainAccess.framework */; productType = "com.apple.product-type.framework"; }; - E4C40E20827836CD754239D105918E4F /* Alamofire */ = { + 84928EB4A33F10E1AA949FEAF3331CBC /* Pods-Services */ = { isa = PBXNativeTarget; - buildConfigurationList = 9B52E2818E288A284E7E71DE0DFE35C1 /* Build configuration list for PBXNativeTarget "Alamofire" */; + buildConfigurationList = F8BFF7D89DB99B737428DD3707FD5D7B /* Build configuration list for PBXNativeTarget "Pods-Services" */; buildPhases = ( - D57537F8758AF7F234DD7F0645E26309 /* Headers */, - EC2CF19A08F6C8803EDA216E982621C2 /* Sources */, - 8DC95DB7322A102F9E7759CA809F36CE /* Frameworks */, - CCE5DC88906544B1A558480C7DCE0B91 /* Resources */, + 8823DEEADB239F8D563D480A7126611F /* Headers */, + CE1417F12B0D403D920EE8649D6BCE20 /* Sources */, + 0D430FA595C12BF6C51B1E5D7DA62489 /* Frameworks */, + C11E7BDF2E6C313A4F60A08E15DCEFF2 /* Resources */, ); buildRules = ( ); dependencies = ( + F9BEA3D05D836C128E1EDBBAFDABF6FA /* PBXTargetDependency */, + A728DED6CCF880273ABA7EFE670E66E8 /* PBXTargetDependency */, + 422FB7CBA9A5E66716BF7D32B20BC3CC /* PBXTargetDependency */, + B064B397B1B19FCEC53DE596BB5C0833 /* PBXTargetDependency */, + C5EC860D7657808CD293D2BD71951F4E /* PBXTargetDependency */, + B2BA21FF54B70130E1D8C04B705D1870 /* PBXTargetDependency */, + 4A2CD178186F35B9D483E5C5673CC3C8 /* PBXTargetDependency */, + ECCC460C69DA33393BD4B7A85952E4A2 /* PBXTargetDependency */, ); - name = Alamofire; - productName = Alamofire; - productReference = 9FDDC29E87B92F93E44BCD9BE2EDED7B /* Alamofire.framework */; + name = "Pods-Services"; + productName = "Pods-Services"; + productReference = 029DC932573FD3CFF2AB08725C770343 /* Pods_Services.framework */; productType = "com.apple.product-type.framework"; }; - E744280562624EB552EEB8C75BBBAB4A /* Pods-Services */ = { + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */ = { isa = PBXNativeTarget; - buildConfigurationList = F9ECB5FE2D8DF5EE0FCF85C2952CBD21 /* Build configuration list for PBXNativeTarget "Pods-Services" */; + buildConfigurationList = C16269269CE2C3CF48FAFB11DDCA540B /* Build configuration list for PBXNativeTarget "GoogleUtilities" */; buildPhases = ( - BAB7389A3DA8E1C9FB8F484A8178E13D /* Headers */, - 0AEC75DEDF8C39B3EF92B88EA1BC70A5 /* Sources */, - 7594253E7AE8385881D06D1D8D1C2F60 /* Frameworks */, - CEE9F721B87464C91E4F356C2A56956D /* Resources */, + 1E515CC83C1A6C69B90E75E32C99344A /* Headers */, + FDE508ACFBAA15FFA7AE92A887609FC4 /* Sources */, + AAEE8989AA8CAA1C579BE02343C9D362 /* Frameworks */, + 9B0D5429D800A5F0CBBC8F98BD8769DB /* Resources */, ); buildRules = ( ); dependencies = ( - 39A3B8F88288B2472FAA586311580ECD /* PBXTargetDependency */, - B83BBAA5E377A68DB0343C0C406DFCCB /* PBXTargetDependency */, - 3256588D1B2A1E44D6E31297A4AC9C7B /* PBXTargetDependency */, - C3AA55F3F868609302660700F91ECC47 /* PBXTargetDependency */, - 492F1C806EE63FC87452FF1527C7C346 /* PBXTargetDependency */, - A4F13434F7453FBD47E9CDA56E377163 /* PBXTargetDependency */, - A8600C5FA7EC185AD3FBE5AFFAD5142D /* PBXTargetDependency */, - 7CBF7F362E6F36F84E7033B8AE5F7218 /* PBXTargetDependency */, ); - name = "Pods-Services"; - productName = "Pods-Services"; - productReference = 8F4D0D3C0C97E223CF4BAEE6393105E9 /* Pods_Services.framework */; + name = GoogleUtilities; + productName = GoogleUtilities; + productReference = B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */; productType = "com.apple.product-type.framework"; }; - EBD7E7BCA2F0D326BAD8C79D06958BDF /* OHHTTPStubs */ = { + 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */ = { isa = PBXNativeTarget; - buildConfigurationList = C91FEE7F75C8B22125948B9539B454A3 /* Build configuration list for PBXNativeTarget "OHHTTPStubs" */; + buildConfigurationList = E242987B250CB1C0EA9B99A80377B33E /* Build configuration list for PBXNativeTarget "SimulatorStatusMagic" */; buildPhases = ( - 61061657344704E38C1BE0A1EC44A71E /* Headers */, - D71D7E32451AD904D55A1EF9D0E8D73D /* Sources */, - 1003DD60B3818FC0B39B8E5E64264D0B /* Frameworks */, - F9F95B720EBA6290FD15CA7731E31BA9 /* Resources */, + BC611EA94FEA3BF8D61D449B9247327D /* Headers */, + 5246328C1BA4A682124E2CDBB1DEE64E /* Sources */, + 4071E424BB335DEAE15B6918D860D684 /* Frameworks */, + FA92C849D249650342DC1C9D39CB9943 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = OHHTTPStubs; - productName = OHHTTPStubs; - productReference = A946DCC1815CEAD36C91124C6248CA37 /* OHHTTPStubs.framework */; + name = SimulatorStatusMagic; + productName = SimulatorStatusMagic; + productReference = A787CDE742CEB6FDF5F73F556D790691 /* SimulatorStatusMagic.framework */; productType = "com.apple.product-type.framework"; }; - FBB1C971E0B9BEBED7A444F93D33FBC1 /* Pods-PRODUCTNAME-PRODUCTNAMETests */ = { + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */ = { isa = PBXNativeTarget; - buildConfigurationList = 128428A69B6EB4E4F59D18E4910240F6 /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME-PRODUCTNAMETests" */; + buildConfigurationList = F7527E454CF938C5B4E80CDBBF13A340 /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */; buildPhases = ( - A9765635F39133BD41CCD8488491A010 /* Headers */, - A90FE0ACE6DC7F926D3B152C1A84DC19 /* Sources */, - 36A98C2CBB2DD03C3AF6D0161881C871 /* Frameworks */, - 3BF14E194D0BADB27FBD1863AB7AF0C8 /* Resources */, + B8851F99376F0F8A8D9CEE158F4A4DF5 /* Headers */, + DA2F1326EFD7678C7B840359CE5AD4BD /* Sources */, + 28D36CD0B6FFBB03EEF67B156AEE1B4C /* Frameworks */, + 14D113BA84B4EB0790747FAAEF8F70E7 /* Resources */, ); buildRules = ( ); dependencies = ( - 5143E83422B6FDCECE8020DFBAE1B6F5 /* PBXTargetDependency */, - 133C6F1B1D8C1CB512586D4B856B0D0F /* PBXTargetDependency */, - 93A3534EFD46D28383E420D6874AE437 /* PBXTargetDependency */, - 6ABF71F3D8C1A4BBF41B3E078C533DA6 /* PBXTargetDependency */, - 49A13DCB25EB716531882742ECD390F9 /* PBXTargetDependency */, - DF3B2703DE597437A07F524FB1A12D3F /* PBXTargetDependency */, - 17C647D5F8467E2A11389C48A37023F3 /* PBXTargetDependency */, - 4CC335DA884F29AD5CE41D7CECC34BFD /* PBXTargetDependency */, - 8BFAF5AABBB3A56B65A55B6CD8312B2F /* PBXTargetDependency */, - B96B1B0D7D41249737296164805E7E78 /* PBXTargetDependency */, - 5A42EBC7DBFDB6370AB709CEA916F84F /* PBXTargetDependency */, - CE019D23CA77341215B1689B3CF9ACBF /* PBXTargetDependency */, - E2228131F0C84FB7D482CB8B6B8F7880 /* PBXTargetDependency */, - 3BA1673D82FC77FE366431D8A5451C26 /* PBXTargetDependency */, + 3131B40EE1FD5708C374043FCDEB6F34 /* PBXTargetDependency */, + BC7EE9A83BC83C8B1EA0B865DB3E3542 /* PBXTargetDependency */, ); - name = "Pods-PRODUCTNAME-PRODUCTNAMETests"; - productName = "Pods-PRODUCTNAME-PRODUCTNAMETests"; - productReference = F562BB9A7020F3CBCE41AE3A3CB94883 /* Pods_PRODUCTNAME_PRODUCTNAMETests.framework */; + name = FirebaseInstanceID; + productName = FirebaseInstanceID; + productReference = 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */; productType = "com.apple.product-type.framework"; }; -/* End PBXNativeTarget section */ + A983A2D06C5B6AA3D6ABA5CCC0A16725 /* OHHTTPStubs */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1B3AA62DD852E489C6FA81F9BAE7F98C /* Build configuration list for PBXNativeTarget "OHHTTPStubs" */; + buildPhases = ( + CD7D21AA0812F3958596A40163651653 /* Headers */, + 14DB4251EE88C3CF6615D70066A2E008 /* Sources */, + F833EC5D09A5161EE957E89F80A80BC7 /* Frameworks */, + F8510BB76B60A76AC6782DABF03116F8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OHHTTPStubs; + productName = OHHTTPStubs; + productReference = 17E33041B314FA837A3CAEB9DF3CDE9F /* OHHTTPStubs.framework */; + productType = "com.apple.product-type.framework"; + }; + BB3523197B248933C6F141B6DC5FCD45 /* Pods-PRODUCTNAME-PRODUCTNAMETests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 860FD77954D8865C1B7965B630EFD07E /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME-PRODUCTNAMETests" */; + buildPhases = ( + 03049833CA31385BB30D4A6974B16E79 /* Headers */, + 7EC84A62F5C6445BBB588B1029A01E3F /* Sources */, + A2696FAB0EC2BE55C4464984FF5957B7 /* Frameworks */, + DCBD146301C92925067AC001E3CAB843 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C6ADDAC46BAE790B5E2894C3F6260371 /* PBXTargetDependency */, + 4137DDB2C909FCCC6EE183822D284889 /* PBXTargetDependency */, + 098C54DAA4FCC297C2C34CF4A339E9BB /* PBXTargetDependency */, + CD3657C180695BFBCC9BB851EF1F5E46 /* PBXTargetDependency */, + 4EC338261083E73909D5E7761E10663A /* PBXTargetDependency */, + 9C0856EC0531FA945CB0621FE3B0AAFB /* PBXTargetDependency */, + 75E9BF21F22F51AE7813D23E3EFC0E63 /* PBXTargetDependency */, + DF830C96531680BABA48C2DEBA893DA2 /* PBXTargetDependency */, + 862FD4C3E56F3C7137D8850907F3977C /* PBXTargetDependency */, + D6CCD2C4CEAD112F1B79C0511A89B945 /* PBXTargetDependency */, + 05F2B7C2AC224938D72C5368FF54B6D6 /* PBXTargetDependency */, + 691941D976E70777EFB79ACA1FAEA580 /* PBXTargetDependency */, + 4211219AAF1105EA85D339F96FAC97C7 /* PBXTargetDependency */, + 454908D79BFF91B366565764B2AA14FB /* PBXTargetDependency */, + B705B74B1463E42DE7E58C97AEF2C0A4 /* PBXTargetDependency */, + 5B23281F47748FD6F812B36B1E0FADA1 /* PBXTargetDependency */, + 1C4DCFA1BE3C33FFE254E4C6ABD23A54 /* PBXTargetDependency */, + D6B9451245EC7F755751840A10706B3B /* PBXTargetDependency */, + 3A831672CE66EA90565FF7F71B378748 /* PBXTargetDependency */, + 0ED8426B13D5F2589FD2F141922C3931 /* PBXTargetDependency */, + 4646A36224F955E4FEE7281D538C5357 /* PBXTargetDependency */, + 6B9755FCC79EF45B735CB71F97B8B2E4 /* PBXTargetDependency */, + A55A50E0AF2679328836112D31C109E0 /* PBXTargetDependency */, + C3CBD8D2CA61651CE4EA1EDFF8CCD19F /* PBXTargetDependency */, + ); + name = "Pods-PRODUCTNAME-PRODUCTNAMETests"; + productName = "Pods-PRODUCTNAME-PRODUCTNAMETests"; + productReference = 8B0B7D7F03E7C5408A9FEDE21398424D /* Pods_PRODUCTNAME_PRODUCTNAMETests.framework */; + productType = "com.apple.product-type.framework"; + }; + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */ = { + isa = PBXNativeTarget; + buildConfigurationList = E481993470B5B9DFECE3140821C2904E /* Build configuration list for PBXNativeTarget "nanopb" */; + buildPhases = ( + 31917A544DEDF75840A86242DA086C54 /* Headers */, + 51D152A4042A7782D0F5D353F38B0335 /* Sources */, + B18D41FB07D1B0D40F34100516637DCE /* Frameworks */, + A3A4F80C8BD691D6FE533EA760B8E453 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = nanopb; + productName = nanopb; + productReference = 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */; + productType = "com.apple.product-type.framework"; + }; + E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = A304035945DB998EEDDC0634D2BF9F26 /* Build configuration list for PBXNativeTarget "Swiftilities" */; + buildPhases = ( + 5ACB9E7F9554486F77804743DD21C9FF /* Headers */, + 1DFF0C3ABC9844B34CAB74D19D7E3047 /* Sources */, + A9CBED312356F3CEFCFBBCD19C51292D /* Frameworks */, + AA45778E54DD71EF3D1CCCCE2892D362 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Swiftilities; + productName = Swiftilities; + productReference = F7696B90A3B3D1C34C7E852254DD74F1 /* Swiftilities.framework */; + productType = "com.apple.product-type.framework"; + }; + EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */ = { + isa = PBXNativeTarget; + buildConfigurationList = 47242F938FAF8F33076BEC83B73F1607 /* Build configuration list for PBXNativeTarget "Alamofire" */; + buildPhases = ( + E1271C58F3B4DED1AC9FAFC325A29CAF /* Headers */, + 03A33151D245B121EBACF7A802F3D6F3 /* Sources */, + 3ABCC0FD127A6AC59FE23898248C80CF /* Frameworks */, + 82C776FC8950365EBBC6FD941521EF6C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Alamofire; + productName = Alamofire; + productReference = 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */; + productType = "com.apple.product-type.framework"; + }; + FCD9915FE83842AE0201096155515772 /* AppCenter-AppCenterDistributeResources */ = { + isa = PBXNativeTarget; + buildConfigurationList = DF9887486229B1728B84F6155310DF6E /* Build configuration list for PBXNativeTarget "AppCenter-AppCenterDistributeResources" */; + buildPhases = ( + FDC0763AA66CE4E9E3DFE8FAB15F9CB4 /* Sources */, + C5AF32A927179B590C49D6A14BF9158E /* Frameworks */, + DAFA3C5C2162D3C04C2CE530638C4F85 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "AppCenter-AppCenterDistributeResources"; + productName = "AppCenter-AppCenterDistributeResources"; + productReference = 11AF731E4071DCD5E34B4CA294302B92 /* AppCenterDistributeResources.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ /* Begin PBXProject section */ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1020; - LastUpgradeCheck = 1020; + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -2061,96 +4068,170 @@ en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 4F93E6BFC4CC76D46B72C7BD14EEAB83 /* Products */; + productRefGroup = C437B8DB3B41FE0E5ACEAF497FD4A0AF /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - E4C40E20827836CD754239D105918E4F /* Alamofire */, - 8D3A1239E052634147734F80F823491B /* Anchorage */, - 2C73C7C87E96DD68B751D61C1033C498 /* BonMot */, - 56C65DE44367A2F21D49CA08AFC9FB3B /* Crashlytics */, - E28CCDDA0BCE0276CB18E6AE6E42CC00 /* Fabric */, - DACB20301113D16B776F458649C04D75 /* GoogleAnalytics */, - 5727E61F2F741F9002936940674C2C4C /* Instabug */, - CCAB7541106C9A08F37141B4E6BABE82 /* KeychainAccess */, - EBD7E7BCA2F0D326BAD8C79D06958BDF /* OHHTTPStubs */, - 09CBDA14CEA10182307DD98DDA2F6826 /* Pods-PRODUCTNAME */, - FBB1C971E0B9BEBED7A444F93D33FBC1 /* Pods-PRODUCTNAME-PRODUCTNAMETests */, - E744280562624EB552EEB8C75BBBAB4A /* Pods-Services */, - 59FF3124354BB8932D3D16CEF7473837 /* SimulatorStatusMagic */, - B3D97E5DFD9D826348C9FD6225F76AC7 /* Sourcery */, - 225EC5F2F324BAAC968D55C764D70D1E /* SwiftGen */, - 19F29DF95D2D1863DFA4C4BE96A51134 /* Swiftilities */, - 9297674709A684A35778E46A8DD2FBF1 /* SwiftLint */, + EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */, + 4607A9D579EE69C57F52971930107170 /* Anchorage */, + A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */, + FCD9915FE83842AE0201096155515772 /* AppCenter-AppCenterDistributeResources */, + 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */, + C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */, + ABB048B191245233986A7CD75FE412A5 /* Fabric */, + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */, + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */, + D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */, + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */, + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */, + 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */, + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */, + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */, + B593490A33943610DC035C394E10D07A /* Instabug */, + 615C831BCE925ED486B225B87E44926D /* KeychainAccess */, + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */, + A983A2D06C5B6AA3D6ABA5CCC0A16725 /* OHHTTPStubs */, + 44E83D2F8D3A4919879F6D9FA69CBC61 /* Pods-PRODUCTNAME */, + BB3523197B248933C6F141B6DC5FCD45 /* Pods-PRODUCTNAME-PRODUCTNAMETests */, + 84928EB4A33F10E1AA949FEAF3331CBC /* Pods-Services */, + 470FE31978DC918618A329D8B55C85FF /* Protobuf */, + 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */, + 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */, + 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */, + E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */, + 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 35E66FB3BA2F891FCB2B465F10406D39 /* Resources */ = { + 14D113BA84B4EB0790747FAAEF8F70E7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1963B15BA5DDF39E925E404B1B5C69D8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D6135916B343D7E548A3F64DBFE6EF8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51833BAA88321210CC48C9DF8B11D18B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64B88C84E52D7233869509EAEC6387F2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 82C776FC8950365EBBC6FD941521EF6C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 88B8A813538905511C304057DC4AC323 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9B0D5429D800A5F0CBBC8F98BD8769DB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 374A8B88C811B644CB8A05599103D6B8 /* Resources */ = { + A3A4F80C8BD691D6FE533EA760B8E453 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 3BF14E194D0BADB27FBD1863AB7AF0C8 /* Resources */ = { + AA45778E54DD71EF3D1CCCCE2892D362 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 464192478BD009031C2F32EDADB8D464 /* Resources */ = { + C11E7BDF2E6C313A4F60A08E15DCEFF2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 4AEF90BB5E5E75F6CF25F29776072502 /* Resources */ = { + C2335386EAEE724F85DA53C2B57D58AC /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 4B4754D0BC19D93992F6BE16833FE0C4 /* Resources */ = { + DAFA3C5C2162D3C04C2CE530638C4F85 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + AED93C5125D8ADFC97325BC4BDEE8F53 /* cs.lproj in Resources */, + C7EC6507F6038550A48154729F095B52 /* de.lproj in Resources */, + A00E351731E9CCAE152C5B88D885F776 /* en.lproj in Resources */, + 8F1FF94F0311B30034EF2698971AD690 /* es.lproj in Resources */, + 10239177A8AE0CD597F3FDCCDAC21FFE /* fr.lproj in Resources */, + 44B74653D503CB502B265C0366ABF103 /* it.lproj in Resources */, + E2B5FF0AD096653DA71FEF1BBDC6233B /* ja.lproj in Resources */, + 91E15F3267E641CB6282B424CE389263 /* ko.lproj in Resources */, + DBC85A7FC433639F2460B8ACA3A55882 /* pl.lproj in Resources */, + EC29582AC7D6FAE74A58A4795B136544 /* pt.lproj in Resources */, + 6F7BC8C09DBD46C7EAB60340AA5AD1A4 /* ru.lproj in Resources */, + AF9BB102EA05092BA8BAB13BCA806CEB /* tr.lproj in Resources */, + 56284F2A2FBC7E52A29EA14CA7DC047A /* zh-Hans.lproj in Resources */, + 8CCB4DFC6700B70BDB65D48791A47479 /* zh-Hant.lproj in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5E853518D740022BFFED5A88E6DC21F8 /* Resources */ = { + DCBD146301C92925067AC001E3CAB843 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - CCE5DC88906544B1A558480C7DCE0B91 /* Resources */ = { + E1E3FEBB4ED67C9E1AF276D80B54F7BA /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - CEE9F721B87464C91E4F356C2A56956D /* Resources */ = { + F8510BB76B60A76AC6782DABF03116F8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - F9F95B720EBA6290FD15CA7731E31BA9 /* Resources */ = { + FA92C849D249650342DC1C9D39CB9943 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -2160,459 +4241,831 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 0AEC75DEDF8C39B3EF92B88EA1BC70A5 /* Sources */ = { + 03A33151D245B121EBACF7A802F3D6F3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7898A06A3FFC4228F5FC1CD65A7B8F94 /* AFError.swift in Sources */, + 625AC25C0B02E9914E2F7B57ECEDB850 /* Alamofire-dummy.m in Sources */, + 7D4B4A11129ABEBE81CF0A75213D2927 /* Alamofire.swift in Sources */, + 7A746727440E0883EC1F855F0CBA10DC /* DispatchQueue+Alamofire.swift in Sources */, + 7B9E46226BDFABC5A56EACCCAB550F13 /* MultipartFormData.swift in Sources */, + 61C1F86EDCE280896041FC1FC3DD8187 /* NetworkReachabilityManager.swift in Sources */, + 59DB4ECFCA9DC741DFF14E4456709E22 /* Notifications.swift in Sources */, + ACF4FD5B728533D8559BB12F6428EC2E /* ParameterEncoding.swift in Sources */, + AC38CF40E73B97EFAB79BBE6B56C8731 /* Request.swift in Sources */, + 3D65EF2ED72527D8BD4359402DC8DE54 /* Response.swift in Sources */, + C1676FB1FF537AED93DB44C1582AC152 /* ResponseSerialization.swift in Sources */, + 2D409981B90BFACE059F7069003F5372 /* Result.swift in Sources */, + 49346BA8A9F65D4EB67A452D73543353 /* ServerTrustPolicy.swift in Sources */, + 2FE5FAA4B2358E5E17D36BDB048F9160 /* SessionDelegate.swift in Sources */, + 4DE36299CE267FCDD391EABEA81FFD85 /* SessionManager.swift in Sources */, + 3684FB4C4B318425C246914FE763A0CC /* TaskDelegate.swift in Sources */, + 2BF26FA6F5CA189C337AD83F534BC3D7 /* Timeline.swift in Sources */, + 5A08019AA5486E6DCA36E4EBD3C52A1F /* Validation.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 14DB4251EE88C3CF6615D70066A2E008 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F08BA4C77195B13666BF9D048734345 /* NSURLRequest+HTTPBodyTesting.m in Sources */, + 50B4399E699415F041C1E8E4DB7A1D07 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */, + 7BDE5F52B1111A7404B4B32EF8C5857E /* OHHTTPStubs-dummy.m in Sources */, + DCED874D6F57DD0E744C345B53E96C3B /* OHHTTPStubs.m in Sources */, + EC85906F2F06B19325232E7A96846CD3 /* OHHTTPStubsMethodSwizzling.m in Sources */, + 4996917AB6F783603F868111BEA8E18B /* OHHTTPStubsResponse+JSON.m in Sources */, + 6C47FCB1BC1088F8D9ECA92E2D2C0EE1 /* OHHTTPStubsResponse.m in Sources */, + D3B02CDBEEA6CB4AFA124B0D8FA73C06 /* OHHTTPStubsSwift.swift in Sources */, + 786F3F286C9376BDF33F3008E351E6F5 /* OHPathHelpers.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1DFF0C3ABC9844B34CAB74D19D7E3047 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6E8015F43C774A2A6B848A4850A5A01B /* AboutView.swift in Sources */, + 515B9D3F0278919FFC0BA69A4A50BF3E /* AccessibilityHelpers.swift in Sources */, + 00B3DFC8711DBA5BEFD89F179EFD44C1 /* AcknowledgementsListViewController.swift in Sources */, + 3B8C1EA2A930ED9F1F28457FF7860F06 /* AcknowledgementsListViewModel.swift in Sources */, + B21176F4F4CEC62BCAFC4FEB1712C2B6 /* AcknowledgementViewController.swift in Sources */, + D33AB83EB8EE0B969A5F68BAF790EC60 /* AppInfo.swift in Sources */, + A263672C857DB63F9F371F1E52FDE51A /* BetterButton.swift in Sources */, + F9956CE423EE435E6B36C133CDD5D27B /* CGFloat+DeviceSize.swift in Sources */, + 84F2EA2BB1C1901EA0A3A1F71919F915 /* CGSize+DeviceSize.swift in Sources */, + 8FD25BB2E0968A8C1C27B4383552FB40 /* Clamping.swift in Sources */, + 9D37E82FFBA10D1CAC0BE6FA8C3B17E2 /* Compatibility.swift in Sources */, + 0B9AC443AC8498AB675F72F8A84D961D /* CoreDataStack.swift in Sources */, + 64608DAE6E2BA2943D7382FC8434201E /* CubicBezier.swift in Sources */, + C2DFB45D6494E63C9993006A15DE55B8 /* CurveProvider.swift in Sources */, + 8D1F1562F8784E50D8E14D44A8B915ED /* DefaultBehaviors.swift in Sources */, + 98F45B8FD93C9BF709915C0ACC7D316D /* DeviceSize.swift in Sources */, + B60414F93325024469AAB0F4B1D4141E /* FeedbackPresenter.swift in Sources */, + C92E53E0F9CE7D32CAEE125353487361 /* FieldValidator.swift in Sources */, + 73C84761F0777ED77BDA9657F0D88C33 /* FloatingPoint+Scale.swift in Sources */, + 133BA9EE26B755C23B694417B33A6936 /* FormattedTextField.swift in Sources */, + CD780A5F99BC76FD2C51EEF2E495CACA /* GradientView.swift in Sources */, + FCEF602D4650E2F192CE13FE12DE83CE /* HairlineView.swift in Sources */, + 8E1D665623C95E8500B9B69BFE963089 /* IndexPath+Extensions.swift in Sources */, + 31F595EB1AE5D570993770123D9A2A5B /* Keyboard.swift in Sources */, + 7D8BB2A430E5C20AF8657A11C9F48016 /* LicenseFormatter.swift in Sources */, + 41D8B6DE590FB9C57F9878F4A384C223 /* LifecycleBehaviorViewController.swift in Sources */, + BAA7A298BF2D071AE6077551CABDA17A /* Log.swift in Sources */, + B1AB9C0D1668DA7D1FB8B05625FE15BB /* NavBarHairlineFadeBehavior.swift in Sources */, + 028B2CECCB9AEA8424D7C00138A38431 /* NavTitleTransitionBehavior.swift in Sources */, + 58052E699714C0A50B87E6259F53F415 /* PlaceholderTextView.swift in Sources */, + 4137F7B8D747E67F776B744E4FF5A116 /* Protocols.swift in Sources */, + 790C5DA2D20D2290D35CD413F051C02D /* Shapes.swift in Sources */, + FBA2DE155485C184B1D2D04B60B5F4F0 /* Swiftilities-dummy.m in Sources */, + D560EF907E1B219904938C32DCA07877 /* TableSection.swift in Sources */, + 02FBDFBD52654C16E8616F45114FAA14 /* TailoredSwiftTextView.swift in Sources */, + D47C36356662BB1CCEC086A9339876E0 /* TintedButton.swift in Sources */, + 9AEA26145F40861CBB60CF404C36C469 /* UIColor+Helpers.swift in Sources */, + 48DD3117F88694C0FD530B7D951E585F /* UIImage+Tinting.swift in Sources */, + 337AF23300B055F9D0AF0BB5AC2F55E9 /* UIStackView+Helpers.swift in Sources */, + 3EA25AB8FC4048123BF2D50D8AEBEFA7 /* UITableView+Extensions.swift in Sources */, + D08829137C1C28D74067CE0D2C9EEF00 /* UITextView+Extensions.swift in Sources */, + 95C6E0D347DA6F768468BF0929F8A84C /* UIView+KeyboardLayoutGuide.swift in Sources */, + 0100B51AAD85D2A5B7C3725618933398 /* UIView+Lookup.swift in Sources */, + 6C12C62F4EB60D4AD5F161942A4D7A1F /* UIViewController+Deselection.swift in Sources */, + A0A162DA5D4BB9A0DAFA3B60DE55130B /* UIViewController+Lifecycle.swift in Sources */, + E93C17002FD7C60CDD5B227371E6AE34 /* UIWindow+RootViewController.swift in Sources */, + 28292C6F27C2567FFD9A0C3130CFC626 /* ViewControllerLifecycleBehavior.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 29333CABA17205542DF156993C524977 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD0155BAAB0AF2CAB66FF0A801DD974 /* AccessibilityHeadingLevel.swift in Sources */, + 1E460A03738161788BA4D0258D3C2657 /* AdaptableTextContainer.swift in Sources */, + E5C352E6C1B3288A651344F557E2A10B /* AdaptiveStyle.swift in Sources */, + 3957709DBEF6C37401EF8F32B962985D /* AdaptiveStyleTransformation.swift in Sources */, + F56B615204B36C3D1287663301D9ED63 /* AttributedStringTransformation.swift in Sources */, + E1C7D68DBCE3516AFDBB93D344E4710D /* BonMot-dummy.m in Sources */, + 06B290D6C5B112EC54DE4AAF0921A969 /* Compatibility.swift in Sources */, + E79E53BD4BED86182EE57B0E7D1FB563 /* Composable.swift in Sources */, + CDA29493785FE82167BBBD3348DFB2D5 /* ContextualAlternates.swift in Sources */, + DC7608F13970D10F8031C34305B4E2FB /* EmbeddedTransformation.swift in Sources */, + 49B7354094136C862C02D3564F82F95C /* Emphasis.swift in Sources */, + F628B678C1D14102D5A6B8E8A369F7FD /* FontFeatures.swift in Sources */, + AFA19EAA3DF13F4E416F836CDE2C1251 /* FontInspector.swift in Sources */, + 672DC3874BA0AB02B90F8C35DE880034 /* Image+Tinting.swift in Sources */, + 5B7FBA1711906689F88D73F89241C604 /* Ligatures.swift in Sources */, + 27168CA32C4871EEE4C1CE2D5909485F /* MutableCopying.swift in Sources */, + D05BF98677EB4739C37C9533E8D877A0 /* NamedStyles.swift in Sources */, + DC6F351B5AAB3C9A2D73772E8BD102B6 /* NSAttributedString+Adaptive.swift in Sources */, + 2EF7C4DD8AE3B593B8DF4E2935543F45 /* NSAttributedString+BonMot.swift in Sources */, + 3AE9A26503715569C678C2C331591663 /* Platform.swift in Sources */, + 002B61DB441C6864402B2620001F2D24 /* Special.swift in Sources */, + 4C1E5B258AF3CD751A7D6DC2F9EFDB64 /* StringStyle+Part.swift in Sources */, + 1FA20690DF9A5043204742E88A203343 /* StringStyle.swift in Sources */, + 67DE466AD41481FEF9115827C53B66FC /* StyleableUIElement.swift in Sources */, + DA1DCD65BFC20A27214C1138C1B92D7F /* StylisticAlternates.swift in Sources */, + 42BC5786C34E1EB3171356AF8E67E607 /* Tab+Adaptive.swift in Sources */, + F8E578B6F9EE4FDDEDF54894A8FCD15C /* Tab.swift in Sources */, + E3A6BE04CAE18910FF90BC707A1B586E /* TextAlignmentConstraint.swift in Sources */, + 42D8642270868B9E53CD23BE32323A0C /* Tracking+Adaptive.swift in Sources */, + E78643D19759C84B84FA5C437DD5C285 /* Tracking.swift in Sources */, + D8C1006C39A3ED7B8F0EBF65D2E66303 /* Transform.swift in Sources */, + 2BD4A62FFC2595A77CF36ECD209FAC2C /* UIKit+AdaptableTextContainerSupport.swift in Sources */, + 8D67D48F9FE60EA4ECB227C7E5E988BA /* UIKit+Helpers.swift in Sources */, + D8342F77FCB434AAD8975E0386F61252 /* XMLBuilder.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A702EEC54A13B2F366712E2E1EAB9DA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - AE53B6D903F4A5991226224B2AE27299 /* Pods-Services-dummy.m in Sources */, + 97C1EB978E9BF15E1F44EA79EAB899E3 /* Keychain.swift in Sources */, + FD8EAE65C4C2FC32FE51494D63D4D180 /* KeychainAccess-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 11619895668C05836EE67CE37E612B01 /* Sources */ = { + 51D152A4042A7782D0F5D353F38B0335 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B634F8070A243AD9742E249A9806C63A /* Keychain.swift in Sources */, - FD6FA1376D516E7308815F44A97856D6 /* KeychainAccess-dummy.m in Sources */, + 7A9842F18B9A92D8C8A029ED721E22B3 /* nanopb-dummy.m in Sources */, + 588888EDDEAB87B7AE65F4417BB0895E /* pb_common.c in Sources */, + 82FEC2B074B1B137D892D51E72F583D5 /* pb_decode.c in Sources */, + 8CDCC6382693D52163B893E94EDE484A /* pb_encode.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 1E4B59E8391364DDF9098377E471A638 /* Sources */ = { + 5246328C1BA4A682124E2CDBB1DEE64E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 63DFF8A1ABBC620D17234C62E5F8100F /* Pods-PRODUCTNAME-dummy.m in Sources */, + DA8774937F99D03BE90B136C8A6A3C55 /* SDStatusBarManager.m in Sources */, + 8B512506674B51BA6D35237363F2B370 /* SDStatusBarOverriderPost10_0.m in Sources */, + AA174969F3D235A0D986C40FA01F8696 /* SDStatusBarOverriderPost10_3.m in Sources */, + 322D81E9DF88D46A7F0B60EF4B7CB1CA /* SDStatusBarOverriderPost11_0.m in Sources */, + 8E1278F983579FE2CCEED68C625ABFF6 /* SDStatusBarOverriderPost12_0.m in Sources */, + 49A539B6B325126F22AC170396E5B6EC /* SDStatusBarOverriderPost8_3.m in Sources */, + 4C650C838B9A46B8869FAC4ED9167B3B /* SDStatusBarOverriderPost9_0.m in Sources */, + E052E19761060467DB062D60D88F5536 /* SDStatusBarOverriderPost9_3.m in Sources */, + B1169761CF66CB7C48BFF5F13A2A89A6 /* SDStatusBarOverriderPre8_3.m in Sources */, + 629542A04865B500B62B43F92C8865D1 /* SimulatorStatusMagic-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7007F55843F87563D364C9E2E9970D1D /* Sources */ = { + 72B8E25E992B707A92C7C56A5B4D1DD0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D92DC1A062A72652A63758BEF8E3940A /* Anchorage-dummy.m in Sources */, - 372D97CF7CC4E40E263C09B1FBC6C4CF /* Anchorage.swift in Sources */, - 8ED42B59366DC0A373B2B2BF5AE77EAE /* AnchorGroupProvider.swift in Sources */, - CD30777B323A5AC47CDCAB7FE59527F0 /* Compatability.swift in Sources */, - BC58D547EF617D867B5C244231BC36C9 /* Internal.swift in Sources */, - 71CF94946674B5B6A64C4CE9B8E34B38 /* NSLayoutAnchor+MultiplierConstraints.swift in Sources */, - 4BEF783784501D68A58DD7A06AE52D8F /* Priority.swift in Sources */, + BD9628048902C3E6580C8916350A4EE7 /* Any.pbobjc.m in Sources */, + F6FF11572A5F8C02E4BA95CD335737E6 /* Api.pbobjc.m in Sources */, + 29F77423AD4D91EA6AA353C23B5C80FA /* Duration.pbobjc.m in Sources */, + 722C5094761B72D30EB0CCB1CBD1BB5A /* Empty.pbobjc.m in Sources */, + 88E84F132638AF1A4D47AC5A0641131F /* FieldMask.pbobjc.m in Sources */, + 3200DB013281B43E28A5C67E98EDCF1B /* GPBArray.m in Sources */, + 9A7E0722E552D06D26AF4A48C0FC02C7 /* GPBCodedInputStream.m in Sources */, + E914909867188AF11D12A4292BBC9729 /* GPBCodedOutputStream.m in Sources */, + 6F7B7BD79C3CFF57A0AA78D63E5E3875 /* GPBDescriptor.m in Sources */, + 8EFC6634D956643DB4EB307460CE67D0 /* GPBDictionary.m in Sources */, + C264488148DA19FD69AD0378C76E7DB9 /* GPBExtensionInternals.m in Sources */, + A0F9B76BF94A692BF96E87085472F70D /* GPBExtensionRegistry.m in Sources */, + 53DC83DDE0F07B1E642EDD0A2FDFCC1B /* GPBMessage.m in Sources */, + DD1C25E78F7402AFE7D53F6CB0EC6459 /* GPBRootObject.m in Sources */, + 969588515E0889063CB93DA45160D18A /* GPBUnknownField.m in Sources */, + D3044F1325FD2E1F21B84CB5E9F5CD86 /* GPBUnknownFieldSet.m in Sources */, + AE2FB5B79FD2943549EF53126CD94862 /* GPBUtilities.m in Sources */, + 12C27A0E31DE9B1B0B5E54C2C429BD54 /* GPBWellKnownTypes.m in Sources */, + D2801FDD33B72D4C72A170C413AA7D71 /* GPBWireFormat.m in Sources */, + 3864DBFDFD3CA45C50C5E35FED55D1C6 /* Protobuf-dummy.m in Sources */, + 817FFB25CEB300C681DBD8283FF19BA1 /* SourceContext.pbobjc.m in Sources */, + 513E4B1817532226E5F18D5BC9616970 /* Struct.pbobjc.m in Sources */, + B2C05E981C8FAAEA0F53F712918CBEBF /* Timestamp.pbobjc.m in Sources */, + 884A014FF635DEF5D4FBF2CED48D3610 /* Type.pbobjc.m in Sources */, + FF7B4E979DC08115710FD5CF868DFABF /* Wrappers.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 797A737D3C14C77D3201D5096C981EEA /* Sources */ = { + 7EC84A62F5C6445BBB588B1029A01E3F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7E465108E9D1294F543867B1C55C3C3F /* AccessibilityHeadingLevel.swift in Sources */, - F9683710500AF59F44487B5D62CB46A0 /* AdaptableTextContainer.swift in Sources */, - 5180B11F592D4E2930C91059A8A0FB21 /* AdaptiveStyle.swift in Sources */, - BA0D738F3F0717185AA235A506E574B1 /* AdaptiveStyleTransformation.swift in Sources */, - 6F449D963205D988420656C9AD1F5A17 /* AttributedStringTransformation.swift in Sources */, - D526BD492A6B5CD97BC93DF45FE859EA /* BonMot-dummy.m in Sources */, - 2B584F0C7B5B845770993315171F672E /* Compatibility.swift in Sources */, - E8943BFB483709F10502286E0FF9C218 /* Composable.swift in Sources */, - 869932972E5299B14D33EE967983B017 /* ContextualAlternates.swift in Sources */, - E64A457BFF181C74C2ED4F46381479A2 /* EmbeddedTransformation.swift in Sources */, - 6C87908248F80080D6B25071845FF921 /* Emphasis.swift in Sources */, - 661122C9F59ACA33B5D6B98BA70DB455 /* FontFeatures.swift in Sources */, - 594443AA4A95549682AB9748FE426BBF /* FontInspector.swift in Sources */, - E530D1A57C985798CF27D8ACDF195330 /* Image+Tinting.swift in Sources */, - DF2657258D6ACA8933FB39795FEB0670 /* Ligatures.swift in Sources */, - B66D7B67F588663DDCEF3033B05970CB /* MutableCopying.swift in Sources */, - 7743E8AE9F8A25C9499A2CC8F5B73D58 /* NamedStyles.swift in Sources */, - 8A4DD3373E0DABD27F453492DC72B098 /* NSAttributedString+Adaptive.swift in Sources */, - 9526DD29040EF10E2E637911921C947B /* NSAttributedString+BonMot.swift in Sources */, - 6F4A5C7A58D039539FF8D80FB810C8BD /* Platform.swift in Sources */, - 029DA4D76E0757FE5918A60D5B6617B7 /* Special.swift in Sources */, - 25C1218514FAF0A2B59655537CEB164F /* StringStyle+Part.swift in Sources */, - 50A0742CD908C7D183E4FE3209DA3F66 /* StringStyle.swift in Sources */, - 3ECC0BDB6024D4967CED3A751D138ACB /* StyleableUIElement.swift in Sources */, - C9B487F21FE826E6875830363BC1ADE6 /* StylisticAlternates.swift in Sources */, - 36A17844B7FA84C2DAA92E9C815F3A9D /* Tab+Adaptive.swift in Sources */, - E418D809C96FE15438768EBA32073EB4 /* Tab.swift in Sources */, - AA31A382B39D9989B540D545D50B9364 /* TextAlignmentConstraint.swift in Sources */, - A3FBBE9D11DBF5311AD8603A99AB803F /* Tracking+Adaptive.swift in Sources */, - B297DD032E18AAA57C8EAB9C413DF7A2 /* Tracking.swift in Sources */, - 9A7534A4ABCC5B65D1D2D7CF5162E7F5 /* Transform.swift in Sources */, - BFAACF3BB3BA01515F386FB5784F868B /* UIKit+AdaptableTextContainerSupport.swift in Sources */, - F0A08B6F139854AB50C4AE7A32EEC7A1 /* UIKit+Helpers.swift in Sources */, - D6218875416D995A010F7D92463FDE49 /* XMLBuilder.swift in Sources */, + 8E307CE212F087956B2835C792FFC79C /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 88877C9EE62BF1149861D26290699A35 /* Sources */ = { + 8AD0FEC519E2F25A92EFA4A40E97C225 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2660387952A6E58B87D43CD72F36967F /* AboutView.swift in Sources */, - E576BAF7FCA60BDCEA9809F47DDA30FD /* AccessibilityHelpers.swift in Sources */, - 39245329F82BE79E611D9375DC1E3FDC /* AcknowledgementsListViewController.swift in Sources */, - 01C5D6067D7B2D44FEBF1E50F5A5E59E /* AcknowledgementsListViewModel.swift in Sources */, - 2CFABA81D7B9737E055D2B7EEF203830 /* AcknowledgementViewController.swift in Sources */, - 351ED3D4D7BB19C3AA1A6B40D6C55A54 /* AppInfo.swift in Sources */, - 1B57410364091178645D752CFB7D5F0E /* BetterButton.swift in Sources */, - 244629EE4387C24F47B469D962A9F30D /* CGFloat+DeviceSize.swift in Sources */, - B2F7BC03C3C341AF9E64A3C5687E2C46 /* CGSize+DeviceSize.swift in Sources */, - 5ABBBE4762B96BA1E1CB6377EE44AEEA /* Clamping.swift in Sources */, - 3E7EF4E43CDFF20CF7029E27C84BDB71 /* Compatibility.swift in Sources */, - 9A8CBEDF59D32AFB564B78EC46995795 /* CoreDataStack.swift in Sources */, - 0AA01A8D182D97EF8EFC886C90F4F047 /* CubicBezier.swift in Sources */, - 3199D76F19D7E097659AA1276AE81547 /* CurveProvider.swift in Sources */, - C09E10BC1C5AE077CFE154E20C184CB7 /* DefaultBehaviors.swift in Sources */, - AC61ED443F5D8F217606A0A59673FEC4 /* DeviceSize.swift in Sources */, - D159754F3CF9C87002B742E85D20CA02 /* FeedbackPresenter.swift in Sources */, - C1B3B07FC6902AD71A16B6D6206F7026 /* FieldValidator.swift in Sources */, - 9BEBA94B220E19FF7106BB065A97676F /* FloatingPoint+Scale.swift in Sources */, - 35A3E179FD493A9B73FFDF67193C0CF9 /* FormattedTextField.swift in Sources */, - 5AFEA52EAFD86CF5A2CBF287BBBE5F19 /* GradientView.swift in Sources */, - 0FA7AA39E8C2A567206C8834E3F39F95 /* HairlineView.swift in Sources */, - A97A129F12231CA847BF2A4DB012F98C /* IndexPath+Extensions.swift in Sources */, - F1766890C65E010081DD7D41C2EF4098 /* Keyboard.swift in Sources */, - 4B02D5480199C26BA2064D60AA872852 /* LicenseFormatter.swift in Sources */, - BB47B70BC730B4DF1A0047DB2AB1E3FF /* LifecycleBehaviorViewController.swift in Sources */, - 57A3D7ACFA17C58BECAFF57D63FC3E27 /* Log.swift in Sources */, - 71FC49E73C6EAFD50619705CDE7F2CEC /* NavBarHairlineFadeBehavior.swift in Sources */, - 043BFE345DC1FEA899CA430F42BBFBFD /* NavTitleTransitionBehavior.swift in Sources */, - A93A28F9BE26581E436CFA6556F9F410 /* PlaceholderTextView.swift in Sources */, - 5166782BDE710463669B746ED5D25342 /* Protocols.swift in Sources */, - 672BA36C53C17E2F3833937232EDCEF4 /* Shapes.swift in Sources */, - E157626B0F43C831B36DF163D864E02F /* Swiftilities-dummy.m in Sources */, - 096B17211F37574FE3BFAF2ACD91D703 /* TableSection.swift in Sources */, - 6AC5E3D32E8EDDC9D4FABDCF58C9668C /* TailoredSwiftTextView.swift in Sources */, - 4D3096DD0BBDA7375893340174F31077 /* TintedButton.swift in Sources */, - E7D43FA3D083CD03552EEEB3FECFEB14 /* UIColor+Helpers.swift in Sources */, - 0441B2B52D9803F39A5D26222BDDFE26 /* UIImage+Tinting.swift in Sources */, - C29A2B46489E9CAC4B750124BC1EA2AD /* UIStackView+Helpers.swift in Sources */, - 677CB0F83DF25BB8756BA7CBCD539150 /* UITableView+Extensions.swift in Sources */, - EFCC6D0B862525E3AE1DAC9598CAD0DA /* UITextView+Extensions.swift in Sources */, - 9FAF65A3D649F0C41F77EBFC9F5D61E4 /* UIView+KeyboardLayoutGuide.swift in Sources */, - 5EC9BE209594B8CEF714DF3344B2698E /* UIView+Lookup.swift in Sources */, - D15BFCBBE9C1D555C15C2F363B1657D2 /* UIViewController+Deselection.swift in Sources */, - A3FA2D02F6245663982D02FF19F12CD0 /* UIViewController+Lifecycle.swift in Sources */, - CADCB575F61C052120F85B0856034D8A /* UIWindow+RootViewController.swift in Sources */, - A0E3993EB2AE9B0327145EC4D40E37A7 /* ViewControllerLifecycleBehavior.swift in Sources */, + 49831F5B3224292A50B5E474627F4066 /* FIRAnalyticsConfiguration.m in Sources */, + 51E49408AF7F12CE0559236B11C26465 /* FIRApp.m in Sources */, + E20902716A8AA163A00FC6FE3817D4C1 /* FIRAppAssociationRegistration.m in Sources */, + 111E7E93B775DC49472ABF1CDC8BD6C7 /* FIRBundleUtil.m in Sources */, + 3322584F7CF6DD027B79F6BCA4651CA1 /* FIRComponent.m in Sources */, + 2612E406DE2FDD81958D99713579DFE4 /* FIRComponentContainer.m in Sources */, + A6DB0753F4D2BE9056C288F6376CD092 /* FIRComponentType.m in Sources */, + D6F46C2555BF94DD17EB5C5137297B7A /* FIRConfiguration.m in Sources */, + 8A3030124B1B48425552E80DADE1FA88 /* FIRDependency.m in Sources */, + 8D56B87617552C4649123F283D3F4383 /* FirebaseCore-dummy.m in Sources */, + 1B5BAD2AE0BDB78D1797A3F079F2DB27 /* FIRErrors.m in Sources */, + F53A883BACBEF618EB01165812EB60A8 /* FIRLogger.m in Sources */, + 3A68C5510ECCCB664B640F57F86435D9 /* FIROptions.m in Sources */, + 69AB47B1E87B21D5AB731A8B4F8A5C6E /* FIRVersion.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A90FE0ACE6DC7F926D3B152C1A84DC19 /* Sources */ = { + B171C95BD079223B02E20B54DAC07B3F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F77E3B7725FBE51D242BC570B80850E /* Pods-PRODUCTNAME-PRODUCTNAMETests-dummy.m in Sources */, + 040519868B2FE15E71CE862276B5FB0D /* Anchorage-dummy.m in Sources */, + 34F9A43BEE167441599A1035E0C14F96 /* Anchorage.swift in Sources */, + A7140404957904FEA7F3949F01B858C0 /* AnchorGroupProvider.swift in Sources */, + B563C657D3678F851A0F8881DC90DB25 /* Compatability.swift in Sources */, + C8BF91ECAD3BF591B752B6C3BCB6761D /* Internal.swift in Sources */, + 13818F8210CF5628758D110549396C75 /* NSLayoutAnchor+MultiplierConstraints.swift in Sources */, + 9307183A631102399452F35E8630D4C1 /* Priority.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - CE7BA0910603A4A551643819336FEB94 /* Sources */ = { + C5EDC2EFB9F2A36C846524DD554C6A16 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C4604B2C39F88DFED999470F29402851 /* SDStatusBarManager.m in Sources */, - 8F94A3B78C0028C3506E5D9450AE1208 /* SDStatusBarOverriderPost10_0.m in Sources */, - 0E3542A5A5F3F9EFA839EDC77195B2CB /* SDStatusBarOverriderPost10_3.m in Sources */, - A5E2A433F778C80CB345B9E240FCFDA7 /* SDStatusBarOverriderPost11_0.m in Sources */, - 56A41DC485A066C2F2CB120BCF3B3984 /* SDStatusBarOverriderPost12_0.m in Sources */, - 048CB1CF7A0E7475798E5CC6EB5FE200 /* SDStatusBarOverriderPost8_3.m in Sources */, - BB6DA79029B5466E4636255DE6CFBE44 /* SDStatusBarOverriderPost9_0.m in Sources */, - 276F0DB6CC331B0F3C7839A3DD151CF0 /* SDStatusBarOverriderPost9_3.m in Sources */, - 9042046A3B8AFC4F7BB5C3D3492BEBB4 /* SDStatusBarOverriderPre8_3.m in Sources */, - 524F2E454EE4A68AC394CB3B4E77EC79 /* SimulatorStatusMagic-dummy.m in Sources */, + 33C1DC1D1DBDCCD13C278B789AC82B0F /* Pods-PRODUCTNAME-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - D71D7E32451AD904D55A1EF9D0E8D73D /* Sources */ = { + CE1417F12B0D403D920EE8649D6BCE20 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DDD1D058B27B2E4F223317D5E483465B /* NSURLRequest+HTTPBodyTesting.m in Sources */, - BF1D822FD50EB7F0312B9A6D5BAA2C67 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */, - 96043478FC52AE27B579B4D4C9BF7E27 /* OHHTTPStubs-dummy.m in Sources */, - 53C5CC3A1581C23558F75CB3C255AC24 /* OHHTTPStubs.m in Sources */, - 60438F5AF861DD37067600E5638048B2 /* OHHTTPStubsMethodSwizzling.m in Sources */, - 81F19671CAE82B5B880CB1DEAA9FA08E /* OHHTTPStubsResponse+JSON.m in Sources */, - 0E272B4F8155B0641E90276663DFBC56 /* OHHTTPStubsResponse.m in Sources */, - C7AFE8108875A1E857C32C951C5F1410 /* OHHTTPStubsSwift.swift in Sources */, - 101E6E896AA3A2A7204E96871FA5BB4B /* OHPathHelpers.m in Sources */, + 623966AD950C81665095F64F9D4201CB /* Pods-Services-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - EC2CF19A08F6C8803EDA216E982621C2 /* Sources */ = { + DA2F1326EFD7678C7B840359CE5AD4BD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 73A4E3A002698D9BED81D3C7E2834222 /* AFError.swift in Sources */, - D5A93AC6B10C26F52943B5E8B28DAA0F /* Alamofire-dummy.m in Sources */, - 3D793A93993A3FEADF5BDF9CF03A365D /* Alamofire.swift in Sources */, - 1A8A306730B51E42994048E5BAC869B6 /* DispatchQueue+Alamofire.swift in Sources */, - 39ACCBA64C7A35BCF9C54D0FEE8462FD /* MultipartFormData.swift in Sources */, - C62B7807668EC142A9113D69D92FE0A8 /* NetworkReachabilityManager.swift in Sources */, - 55FBD894BA4FD15AAA7C9ACAD7EC3794 /* Notifications.swift in Sources */, - 76042774D794C5BA362A7CC2C6D3035D /* ParameterEncoding.swift in Sources */, - A8D5B034D56D54FC40D8F8F7CD25ADC1 /* Request.swift in Sources */, - 492774AF8B865F9BC7209B3B3B258A51 /* Response.swift in Sources */, - 59E5F1CE40CED4315B46012E19E626FA /* ResponseSerialization.swift in Sources */, - 283F3373EAC068D98EA40E496B066D33 /* Result.swift in Sources */, - 0A33AECCF24B7B360AD0753C85DDC0BE /* ServerTrustPolicy.swift in Sources */, - 3C683D8D80512159018867E961184EE6 /* SessionDelegate.swift in Sources */, - 06F4ABBA147243A15DD55ED5F8E27843 /* SessionManager.swift in Sources */, - 54C8E467F3E3EF20E3896D98AB5E6551 /* TaskDelegate.swift in Sources */, - 680B1E03B052C11DE3E6ABC9A5387F8F /* Timeline.swift in Sources */, - E9B689D5EA5275942FB3A8FAF46A234D /* Validation.swift in Sources */, + 5D01F5103E9821505EF578009E14403E /* FirebaseInstanceID-dummy.m in Sources */, + 660EE0BDDC1B6E8665904E38D90D31C6 /* FIRInstanceID+Private.m in Sources */, + 203BE416FA99DFA5A8A48CBFD3D12D1D /* FIRInstanceID.m in Sources */, + 44FB46D5982B3E156F7AA4BEE081B463 /* FIRInstanceIDAPNSInfo.m in Sources */, + 68F48879AF4FFB5542723DDF132E7BBF /* FIRInstanceIDAuthKeyChain.m in Sources */, + 5709B0AB8B9B6E3FD552E4D0E72A40E5 /* FIRInstanceIDAuthService.m in Sources */, + 730B332BFCCE80D74F954AB5D5018B07 /* FIRInstanceIDBackupExcludedPlist.m in Sources */, + 75B139101E0BFF3585B49F931BE977F2 /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */, + D7B354F43D71BF171E85F1A3D460C027 /* FIRInstanceIDCheckinPreferences.m in Sources */, + 75123AA17FF6CF721675F5EFB25EC559 /* FIRInstanceIDCheckinService.m in Sources */, + E88F998AF2E3FABE07308B1454182029 /* FIRInstanceIDCheckinStore.m in Sources */, + 39074F282BFA3893780C3F2330271BFA /* FIRInstanceIDCombinedHandler.m in Sources */, + 7AB1BE129580DE43994C27204D3D9F97 /* FIRInstanceIDConstants.m in Sources */, + 3DA83DFE11641ABBF54EED0F6D91658C /* FIRInstanceIDKeychain.m in Sources */, + A605E2BA73843B1BF04318D1F249E7D8 /* FIRInstanceIDKeyPair.m in Sources */, + D0015B5606D3E07958B6F40D8625B8F0 /* FIRInstanceIDKeyPairStore.m in Sources */, + AB7B824DA74A18F8F235023186B0CB99 /* FIRInstanceIDKeyPairUtilities.m in Sources */, + E27438C8E65CF4DAC905C6026EBACC35 /* FIRInstanceIDLogger.m in Sources */, + 90CDCAD92FF576BA1E27CAC55DF10C91 /* FIRInstanceIDStore.m in Sources */, + 5762BA089A3300D0CC1348BB1C6BF5D0 /* FIRInstanceIDStringEncoding.m in Sources */, + 0E47DE1D5D4C7AA8034D1B7F63774BF0 /* FIRInstanceIDTokenDeleteOperation.m in Sources */, + A4D4A302AEEB0666AEB08B226637D78E /* FIRInstanceIDTokenFetchOperation.m in Sources */, + 79D254191EAC73996F5BD06EFFA4E649 /* FIRInstanceIDTokenInfo.m in Sources */, + EB3DC0691CBB0AF117F1D9D442FA67AA /* FIRInstanceIDTokenManager.m in Sources */, + 40CAB5AAB5CF579001117DA2892ABA3B /* FIRInstanceIDTokenOperation.m in Sources */, + FC9D03E94B1D4725AAA52ED0AFD5463F /* FIRInstanceIDTokenStore.m in Sources */, + 66E368242E78C0FD771A32B6FE1931A8 /* FIRInstanceIDURLQueryItem.m in Sources */, + B5E3F3D139F7AC7686281E983CAEC0B9 /* FIRInstanceIDUtilities.m in Sources */, + DA40FB231BD634D57A958BF90B7D27B0 /* FIRInstanceIDVersionUtilities.m in Sources */, + 1F680A61812FACE2D5115195328CA3DF /* NSError+FIRInstanceID.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ECAA69750FA4F99D92214CCBCCDAF45E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2646BB4FDA2D1690D9DA61405740F25C /* FirebaseMessaging-dummy.m in Sources */, + 63EACF4772E7F89957A22DD4E216C3F6 /* FIRMessaging.m in Sources */, + A6413A77105FCE014808660C4A174018 /* FIRMessagingAnalytics.m in Sources */, + 8625F2607D15296CF239BC97F7BB3EE6 /* FIRMessagingCheckinService.m in Sources */, + 776CAB01CC996B0FBA52C7C6872F0814 /* FIRMessagingClient.m in Sources */, + E851CD56878C963DD7E0CD660FBE4D22 /* FIRMessagingCodedInputStream.m in Sources */, + D7F5B4B7FF371A59B9F5625EC8ECAA7E /* FIRMessagingConnection.m in Sources */, + 6B9902DEB83C255B7F7BE5B97D95CB8C /* FIRMessagingConstants.m in Sources */, + 1B8BC5D48142213B30D7DB0D0B067738 /* FIRMessagingContextManagerService.m in Sources */, + AE1DA43BC4C87D79899149013C1DAD98 /* FIRMessagingDataMessageManager.m in Sources */, + C8AC529DAADB07541D2D33E392CDF169 /* FIRMessagingDelayedMessageQueue.m in Sources */, + 8E06E338A8F1324484A07E102C6085CB /* FIRMessagingExtensionHelper.m in Sources */, + F7CA527CFEF6E3DE6466C6D66D138346 /* FIRMessagingLogger.m in Sources */, + 46132B8EB028FC0BD59C6B8293151984 /* FIRMessagingPacketQueue.m in Sources */, + 6A54BA358BA6EA4B21A472B16B0F2136 /* FIRMessagingPendingTopicsList.m in Sources */, + DD34CF52B04302F2F486A626A57EBE9B /* FIRMessagingPersistentSyncMessage.m in Sources */, + EB9352F06FF1E5906D9D91135967ABB8 /* FIRMessagingPubSub.m in Sources */, + ADEAD2F9475DADEA607C02D303956EBC /* FIRMessagingPubSubRegistrar.m in Sources */, + 70A61B041ADCE42401597F1F1E36A137 /* FIRMessagingReceiver.m in Sources */, + 1735E3217A03B5B4EEFF084033ABE1DD /* FIRMessagingRegistrar.m in Sources */, + 922299C14975D3257CEA7CD05B8230AA /* FIRMessagingRemoteNotificationsProxy.m in Sources */, + 3A1C7551BF0986016F6C2537B5E2733F /* FIRMessagingRmq2PersistentStore.m in Sources */, + F4D84858653EFDD2A8738A28176A44E4 /* FIRMessagingRmqManager.m in Sources */, + E1355ABFA24FFFE7788FFC23A0E5543D /* FIRMessagingSecureSocket.m in Sources */, + CA9D644E80935F7226B7D7105E837792 /* FIRMessagingSyncMessageManager.m in Sources */, + DD904DE0D282B9A9724B76536A085559 /* FIRMessagingTopicOperation.m in Sources */, + E2C7E5A5A237425DA4C72EFF01475076 /* FIRMessagingUtilities.m in Sources */, + 39CE61B6B67AAA879293052A016A9B44 /* FIRMessagingVersionUtilities.m in Sources */, + 857CEBBEB16312172E8DF03B1147377B /* GtalkCore.pbobjc.m in Sources */, + A2C760AD1904241031DE9DDD5DB0E935 /* GtalkExtensions.pbobjc.m in Sources */, + DCE2544D0E3CA203C5FC20C01510DDC3 /* NSDictionary+FIRMessaging.m in Sources */, + 1931E725A11B3C13986AB78A8130111C /* NSError+FIRMessaging.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDC0763AA66CE4E9E3DFE8FAB15F9CB4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDE508ACFBAA15FFA7AE92A887609FC4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 80975D2BEC9BBEB5D026A75D9A42B6B2 /* GoogleUtilities-dummy.m in Sources */, + 748616D83CFB8AD5D5FC47C2EDB8FF36 /* GULAppDelegateSwizzler.m in Sources */, + F36D0E75366326FACC9EB8DE7F4F98F4 /* GULAppEnvironmentUtil.m in Sources */, + 0D9138EF60798B8D013C354FFC3F956C /* GULLogger.m in Sources */, + CB0F1A83E1DFE29F971867BFB285B59D /* GULMutableDictionary.m in Sources */, + 8EC15CDA263AE10AF1D49B82794AFBB4 /* GULNetwork.m in Sources */, + 4D4DD4E2E2F97F489820569260C7BBEF /* GULNetworkConstants.m in Sources */, + 1A57D555A841083C708009478DC31FB5 /* GULNetworkURLSession.m in Sources */, + 1B586862269C42A863000C3B70991A0B /* GULNSData+zlib.m in Sources */, + 3A6073E24514DD7FC8539E5C9BD6FF3F /* GULReachabilityChecker.m in Sources */, + 18104AFA575A3CFB614915516FA8A1EF /* GULSwizzler.m in Sources */, + 59797280DBA2DF4FDD7E2FB08A37D99B /* GULUserDefaults.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 133C6F1B1D8C1CB512586D4B856B0D0F /* PBXTargetDependency */ = { + 027A71A52AB8D3D436ECDC9CB733277E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Anchorage; - target = 8D3A1239E052634147734F80F823491B /* Anchorage */; - targetProxy = A33EA930646776DF7C00CC7A87A026B5 /* PBXContainerItemProxy */; + name = AppCenter; + target = A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */; + targetProxy = DF4A594B4218CCA9EF0D5B89B5EFB551 /* PBXContainerItemProxy */; }; - 17C647D5F8467E2A11389C48A37023F3 /* PBXTargetDependency */ = { + 05F2B7C2AC224938D72C5368FF54B6D6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Instabug; - target = 5727E61F2F741F9002936940674C2C4C /* Instabug */; - targetProxy = 49F3EAF1D7395F993FB1E1379E25E6D5 /* PBXContainerItemProxy */; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = BAE33B3D752C070CD5F2887D4F50B516 /* PBXContainerItemProxy */; }; - 1EC5FE0850099251D925B46186DF3B25 /* PBXTargetDependency */ = { + 098C54DAA4FCC297C2C34CF4A339E9BB /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SwiftLint; - target = 9297674709A684A35778E46A8DD2FBF1 /* SwiftLint */; - targetProxy = 43BDBE6C7740556BACD88519F785BC8B /* PBXContainerItemProxy */; + name = AppCenter; + target = A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */; + targetProxy = 1F2EFDBE486B46D9BB0ACA670DCE64E5 /* PBXContainerItemProxy */; }; - 3256588D1B2A1E44D6E31297A4AC9C7B /* PBXTargetDependency */ = { + 0C26C138EB21155893EB3AAE8342452D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = BonMot; - target = 2C73C7C87E96DD68B751D61C1033C498 /* BonMot */; - targetProxy = 107F5858160D61E0A3DA5D8722578633 /* PBXContainerItemProxy */; + name = FirebaseMessaging; + target = 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */; + targetProxy = E50E5C34A42ACE328C4D101E74D0E458 /* PBXContainerItemProxy */; }; - 39A3B8F88288B2472FAA586311580ECD /* PBXTargetDependency */ = { + 0ED8426B13D5F2589FD2F141922C3931 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Alamofire; - target = E4C40E20827836CD754239D105918E4F /* Alamofire */; - targetProxy = AC68A476D2DE351C94651D7AA9E67190 /* PBXContainerItemProxy */; + name = Sourcery; + target = 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */; + targetProxy = 4C4B6E49A1CB5F547EF7EDA8A2894B2E /* PBXContainerItemProxy */; }; - 3BA1673D82FC77FE366431D8A5451C26 /* PBXTargetDependency */ = { + 1C4DCFA1BE3C33FFE254E4C6ABD23A54 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Swiftilities; - target = 19F29DF95D2D1863DFA4C4BE96A51134 /* Swiftilities */; - targetProxy = E8AB0247FAB907CD91CA25733C2B8A28 /* PBXContainerItemProxy */; + name = OHHTTPStubs; + target = A983A2D06C5B6AA3D6ABA5CCC0A16725 /* OHHTTPStubs */; + targetProxy = 3103E425B0EDFA9736C768A7D3E015B9 /* PBXContainerItemProxy */; + }; + 21126DE93342F0CFC72E8B0BFF74B7C2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 4809F369638E77D13FBA5FDDC4B279F0 /* PBXContainerItemProxy */; }; - 423CB78AC3BE7CB1E8B3C87FBCAD5DE1 /* PBXTargetDependency */ = { + 3131B40EE1FD5708C374043FCDEB6F34 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 543BCBF2DF409AB1D8FBE0BB138681A9 /* PBXContainerItemProxy */; + }; + 34CC4B4491776D9C45A351FBC15D65D4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SimulatorStatusMagic; - target = 59FF3124354BB8932D3D16CEF7473837 /* SimulatorStatusMagic */; - targetProxy = 732E977BD587A7949D21277805A7F263 /* PBXContainerItemProxy */; + target = 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */; + targetProxy = CCD653DB7DAA28F82561ABBA8580BADE /* PBXContainerItemProxy */; }; - 492F1C806EE63FC87452FF1527C7C346 /* PBXTargetDependency */ = { + 3792EB87049BCC72EB8B88E35FC33ADB /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Sourcery; - target = B3D97E5DFD9D826348C9FD6225F76AC7 /* Sourcery */; - targetProxy = 26E5945A14D4DB45F770936B3EFFC598 /* PBXContainerItemProxy */; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 66BF61E910A9B80A8316776974C2BB95 /* PBXContainerItemProxy */; }; - 49A13DCB25EB716531882742ECD390F9 /* PBXTargetDependency */ = { + 3A831672CE66EA90565FF7F71B378748 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Fabric; - target = E28CCDDA0BCE0276CB18E6AE6E42CC00 /* Fabric */; - targetProxy = D11C6E9AF90019984BFAE36131AD4336 /* PBXContainerItemProxy */; + name = SimulatorStatusMagic; + target = 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */; + targetProxy = E9C5672F0CD0FA063A46323C4AC136D2 /* PBXContainerItemProxy */; }; - 4CC335DA884F29AD5CE41D7CECC34BFD /* PBXTargetDependency */ = { + 4137DDB2C909FCCC6EE183822D284889 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = KeychainAccess; - target = CCAB7541106C9A08F37141B4E6BABE82 /* KeychainAccess */; - targetProxy = 129F9FCC6AD4F059B7703A766CAA819E /* PBXContainerItemProxy */; + name = Anchorage; + target = 4607A9D579EE69C57F52971930107170 /* Anchorage */; + targetProxy = 5B756F4043C0BF271158008CDED79D84 /* PBXContainerItemProxy */; }; - 5143E83422B6FDCECE8020DFBAE1B6F5 /* PBXTargetDependency */ = { + 4211219AAF1105EA85D339F96FAC97C7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Alamofire; - target = E4C40E20827836CD754239D105918E4F /* Alamofire */; - targetProxy = 977879763DF2C70A04DACC092D0BCF03 /* PBXContainerItemProxy */; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = E327328558089D481E112C8A4A506DE5 /* PBXContainerItemProxy */; + }; + 422FB7CBA9A5E66716BF7D32B20BC3CC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = BonMot; + target = 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */; + targetProxy = 61CD1DC5DB1618415917A6B6B148544A /* PBXContainerItemProxy */; + }; + 454908D79BFF91B366565764B2AA14FB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = A57D1B3D3A7F6453569CBAD3F3B57B2B /* PBXContainerItemProxy */; }; - 552F17ED96982496E47F141C3848E90C /* PBXTargetDependency */ = { + 4646A36224F955E4FEE7281D538C5357 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftGen; - target = 225EC5F2F324BAAC968D55C764D70D1E /* SwiftGen */; - targetProxy = 9C240FDBE0F83173CE9EFAD71689332D /* PBXContainerItemProxy */; + target = 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */; + targetProxy = 95B892EE3C9D4BCC89AA02E77558C5CF /* PBXContainerItemProxy */; + }; + 4A2CD178186F35B9D483E5C5673CC3C8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = DF66A2F4782D1A0979660E315CF32196 /* PBXContainerItemProxy */; }; - 56074B1A6858DF2148C6F8AB33AB2B8C /* PBXTargetDependency */ = { + 4C5E8A7AE78E64723705A8C4F39294C2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Alamofire; - target = E4C40E20827836CD754239D105918E4F /* Alamofire */; - targetProxy = DF1614AEEACBB691AA7E18F35946DA0E /* PBXContainerItemProxy */; + target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */; + targetProxy = 47C1327AD0E022A8CAD8A8A249109E10 /* PBXContainerItemProxy */; }; - 599A74641EEF5EFE5AFC566B1670B92B /* PBXTargetDependency */ = { + 4EC338261083E73909D5E7761E10663A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Sourcery; - target = B3D97E5DFD9D826348C9FD6225F76AC7 /* Sourcery */; - targetProxy = 4C59DDA516F65563F41EAC3E60B1D180 /* PBXContainerItemProxy */; + name = Crashlytics; + target = C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */; + targetProxy = 2E46EEE58DA8EA73341280992D1C5D13 /* PBXContainerItemProxy */; }; - 5A42EBC7DBFDB6370AB709CEA916F84F /* PBXTargetDependency */ = { + 509CCF144E767C197328128D373A1367 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Sourcery; - target = B3D97E5DFD9D826348C9FD6225F76AC7 /* Sourcery */; - targetProxy = 17BAAF8271678B85C41D37005E6590DE /* PBXContainerItemProxy */; + name = FirebaseAnalyticsInterop; + target = D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */; + targetProxy = 1FDC68635BD8EB1847D7ABA3BDED5D08 /* PBXContainerItemProxy */; }; - 6ABF71F3D8C1A4BBF41B3E078C533DA6 /* PBXTargetDependency */ = { + 517C4D4310C32500D8D3C4AFB217A87A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Crashlytics; - target = 56C65DE44367A2F21D49CA08AFC9FB3B /* Crashlytics */; - targetProxy = 62BF750024C73BD63BBB5D26CAE963FC /* PBXContainerItemProxy */; + name = Protobuf; + target = 470FE31978DC918618A329D8B55C85FF /* Protobuf */; + targetProxy = 148469CADF8690152BAB10A58272A43F /* PBXContainerItemProxy */; }; - 70EF66862FFA076DC90801BA25B2E000 /* PBXTargetDependency */ = { + 57A98EA8D303A644FA7B50E4295B8171 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = C6B51788BF5B5F1CA75F34172EAC8C66 /* PBXContainerItemProxy */; + }; + 5B23281F47748FD6F812B36B1E0FADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KeychainAccess; + target = 615C831BCE925ED486B225B87E44926D /* KeychainAccess */; + targetProxy = B269AA35A62F09500537A4BA3BFB44C3 /* PBXContainerItemProxy */; + }; + 5C27114E1234A898AE9167984987A6BB /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Instabug; - target = 5727E61F2F741F9002936940674C2C4C /* Instabug */; - targetProxy = EF2E574032F4C13F51E21EA063963A2C /* PBXContainerItemProxy */; + target = B593490A33943610DC035C394E10D07A /* Instabug */; + targetProxy = 5802AA2B78C7A3E6CF58C77D762D71E9 /* PBXContainerItemProxy */; }; - 7610E8B6599E214698ABF758DE110C52 /* PBXTargetDependency */ = { + 5CE6985057CE4B265103CF4F42193E36 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Anchorage; - target = 8D3A1239E052634147734F80F823491B /* Anchorage */; - targetProxy = F1A311C6FA88CF80A388ED605152118B /* PBXContainerItemProxy */; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = 02B643491EF1939B6406629306F2675E /* PBXContainerItemProxy */; }; - 7CBF7F362E6F36F84E7033B8AE5F7218 /* PBXTargetDependency */ = { + 5F429333A5E8F5B0843B8383C878CEDD /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Swiftilities; - target = 19F29DF95D2D1863DFA4C4BE96A51134 /* Swiftilities */; - targetProxy = F84E9C29E13B34282E85294A32AE6BE4 /* PBXContainerItemProxy */; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = BE218348DB050D18EB6D52F098627920 /* PBXContainerItemProxy */; }; - 8BFAF5AABBB3A56B65A55B6CD8312B2F /* PBXTargetDependency */ = { + 691941D976E70777EFB79ACA1FAEA580 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = OHHTTPStubs; - target = EBD7E7BCA2F0D326BAD8C79D06958BDF /* OHHTTPStubs */; - targetProxy = 0B3D5FE4B66C1AA4786B9173C45FF5AB /* PBXContainerItemProxy */; + name = FirebaseMessaging; + target = 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */; + targetProxy = F08459BC4BC97915AAF676A70BA1044E /* PBXContainerItemProxy */; }; - 9201B31C41B3922CD779EC77C152646A /* PBXTargetDependency */ = { + 6B9755FCC79EF45B735CB71F97B8B2E4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Swiftilities; - target = 19F29DF95D2D1863DFA4C4BE96A51134 /* Swiftilities */; - targetProxy = 3A1A8050DFC1EA428BB3F414DF269AA1 /* PBXContainerItemProxy */; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = DCD1C96ECC57BB8FC7BB0C12A709B9F1 /* PBXContainerItemProxy */; + }; + 72C383DDA0C3B15B45C1BBE8168E7C32 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Fabric; + target = ABB048B191245233986A7CD75FE412A5 /* Fabric */; + targetProxy = 3DB056970030F95365323DB7D483F0E4 /* PBXContainerItemProxy */; + }; + 73A206221EDC7792C0724E183F29C491 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 93FC40FACD2A3CAE5B749D36454B21BA /* PBXContainerItemProxy */; }; - 93A3534EFD46D28383E420D6874AE437 /* PBXTargetDependency */ = { + 75E9BF21F22F51AE7813D23E3EFC0E63 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = FCB8621B4850804581799AA75D809CD9 /* PBXContainerItemProxy */; + }; + 76368B6D12BB326EEFA9898C11C103BF /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = BonMot; - target = 2C73C7C87E96DD68B751D61C1033C498 /* BonMot */; - targetProxy = 8F1AB109557454819AC6FB736B4C2EC8 /* PBXContainerItemProxy */; + target = 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */; + targetProxy = F83820FC705E1ACB652B680E9ED10441 /* PBXContainerItemProxy */; }; - 9B9AA20443840191F6C4335D9DD7FE12 /* PBXTargetDependency */ = { + 790A3D878446B70A5A20256D674AB5E1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = GoogleAnalytics; - target = DACB20301113D16B776F458649C04D75 /* GoogleAnalytics */; - targetProxy = 88B6355FFB5EE4E71FC2376CD9BD082A /* PBXContainerItemProxy */; + name = Crashlytics; + target = C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */; + targetProxy = 5377C294E50C7447C27E7C2D9D0BC8C4 /* PBXContainerItemProxy */; }; - A4F13434F7453FBD47E9CDA56E377163 /* PBXTargetDependency */ = { + 80661FD0776FF5CE9CEA1E2D72C1B901 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SwiftGen; - target = 225EC5F2F324BAAC968D55C764D70D1E /* SwiftGen */; - targetProxy = A85E0153EF5D7727753CFA1B149A4B2F /* PBXContainerItemProxy */; + name = FirebaseMessaging; + target = 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */; + targetProxy = 689919C1E5546B4C5075358DC52F3565 /* PBXContainerItemProxy */; }; - A8600C5FA7EC185AD3FBE5AFFAD5142D /* PBXTargetDependency */ = { + 83F2C143D8BEF77B7C4759F0CAFB4E62 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SwiftLint; - target = 9297674709A684A35778E46A8DD2FBF1 /* SwiftLint */; - targetProxy = F2ABE20F2506CF359EEE59DB74D89683 /* PBXContainerItemProxy */; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = 2A7CCB51109B88316A5FC993FB897CEB /* PBXContainerItemProxy */; + }; + 862FD4C3E56F3C7137D8850907F3977C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalyticsInterop; + target = D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */; + targetProxy = F3A392E1ED6D4068A572BD13DC958074 /* PBXContainerItemProxy */; + }; + 912865061B33024F53771995A880334E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Protobuf; + target = 470FE31978DC918618A329D8B55C85FF /* Protobuf */; + targetProxy = 1BF24697EA008F1406020E754EF90367 /* PBXContainerItemProxy */; + }; + 9C0856EC0531FA945CB0621FE3B0AAFB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Fabric; + target = ABB048B191245233986A7CD75FE412A5 /* Fabric */; + targetProxy = 5576D78AFE2208B1EEFB5282D84D1F08 /* PBXContainerItemProxy */; + }; + 9F9E6213111F42F60CF9E3049030C0EC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = F7B77B6FF52752D1C86E594584C3D247 /* PBXContainerItemProxy */; + }; + A3560B04C6C7550C49D3509E4F985634 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = CC51CF93141CEA0C62DE97225C0BC04E /* PBXContainerItemProxy */; }; - B83BBAA5E377A68DB0343C0C406DFCCB /* PBXTargetDependency */ = { + A55A50E0AF2679328836112D31C109E0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Swiftilities; + target = E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */; + targetProxy = 1A12587DD794CA9955F23A75370F8EAD /* PBXContainerItemProxy */; + }; + A728DED6CCF880273ABA7EFE670E66E8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Anchorage; - target = 8D3A1239E052634147734F80F823491B /* Anchorage */; - targetProxy = 6603F971020D3767F8FB7DE1933C5576 /* PBXContainerItemProxy */; + target = 4607A9D579EE69C57F52971930107170 /* Anchorage */; + targetProxy = C80C2AF874999BC32CD68D52CF8B6442 /* PBXContainerItemProxy */; }; - B96B1B0D7D41249737296164805E7E78 /* PBXTargetDependency */ = { + A8FE2505F0526DA98700BDEF778002CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SimulatorStatusMagic; - target = 59FF3124354BB8932D3D16CEF7473837 /* SimulatorStatusMagic */; - targetProxy = 4994FF095EEECB5DC82D47D24221AF6B /* PBXContainerItemProxy */; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = D9CCC0B18E86FDC85771011139ACDCD4 /* PBXContainerItemProxy */; }; - C3AA55F3F868609302660700F91ECC47 /* PBXTargetDependency */ = { + B064B397B1B19FCEC53DE596BB5C0833 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = KeychainAccess; - target = CCAB7541106C9A08F37141B4E6BABE82 /* KeychainAccess */; - targetProxy = 8AFC34FD9107620797D08F617071FE3A /* PBXContainerItemProxy */; + target = 615C831BCE925ED486B225B87E44926D /* KeychainAccess */; + targetProxy = DB41FC5EB5ED2499B0E89BB46AA4359B /* PBXContainerItemProxy */; + }; + B246D60A4784E7242E6F9573F6581752 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 75EA1E73941199F90021A0EBD5ED4264 /* PBXContainerItemProxy */; + }; + B2BA21FF54B70130E1D8C04B705D1870 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftGen; + target = 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */; + targetProxy = 08148E3EFA12C37CE29E49C3C7EF9167 /* PBXContainerItemProxy */; + }; + B5290BC5AF5A74B7D2919728FDE4472E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 4C0638D0D195A9000851F687C36E3AF2 /* PBXContainerItemProxy */; + }; + B59975B1711C1B93F51408259602A32F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = DEF897143670388E42D9901AD7FECCDC /* PBXContainerItemProxy */; + }; + B705B74B1463E42DE7E58C97AEF2C0A4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Instabug; + target = B593490A33943610DC035C394E10D07A /* Instabug */; + targetProxy = FE3AF2118BF9BD4601F3A147DBC26D4C /* PBXContainerItemProxy */; + }; + BC7EE9A83BC83C8B1EA0B865DB3E3542 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 6ECBB905773B62DD8276A7843DE12298 /* PBXContainerItemProxy */; + }; + BC9C5B4317B57C84FDC286747A6C68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "AppCenter-AppCenterDistributeResources"; + target = FCD9915FE83842AE0201096155515772 /* AppCenter-AppCenterDistributeResources */; + targetProxy = FC1D9ED47627FC05FEF6B4B3B5CDB53C /* PBXContainerItemProxy */; + }; + C3CBD8D2CA61651CE4EA1EDFF8CCD19F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 73FE5A0BD5D3991167C7C54DD4D446DA /* PBXContainerItemProxy */; + }; + C4D6DC5312308B518D11684361884474 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 7A591D0D32FC2DC7C5953B14551C8425 /* PBXContainerItemProxy */; + }; + C5EC860D7657808CD293D2BD71951F4E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sourcery; + target = 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */; + targetProxy = 33807B5A769F0C36650DF5EE9C76AB54 /* PBXContainerItemProxy */; + }; + C6ADDAC46BAE790B5E2894C3F6260371 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Alamofire; + target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */; + targetProxy = B5EC11065BDE7CEAB67D207F576271FB /* PBXContainerItemProxy */; }; C9EE7669C499C214D32673DA70F448B1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Fabric; - target = E28CCDDA0BCE0276CB18E6AE6E42CC00 /* Fabric */; + target = ABB048B191245233986A7CD75FE412A5 /* Fabric */; targetProxy = BF2E36C9AB9868362ECE4F7D15CA684C /* PBXContainerItemProxy */; }; - CE019D23CA77341215B1689B3CF9ACBF /* PBXTargetDependency */ = { + CCB4B2FB4874EF61E26C0C42BF0A95E6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 689D82AE9C6AAEF561CBC45F0C3F37D8 /* PBXContainerItemProxy */; + }; + CD3657C180695BFBCC9BB851EF1F5E46 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = BonMot; + target = 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */; + targetProxy = 2E884F9A0CD78CCADB89B607F8BDB639 /* PBXContainerItemProxy */; + }; + D0405CD352F9BA331E0835E76731E1D5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftGen; - target = 225EC5F2F324BAAC968D55C764D70D1E /* SwiftGen */; - targetProxy = 2B0538B0EAB1AB09A690575AAEB41DCC /* PBXContainerItemProxy */; + target = 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */; + targetProxy = BBA3C65F4427758819F8FE0EB02A684A /* PBXContainerItemProxy */; }; - DF3B2703DE597437A07F524FB1A12D3F /* PBXTargetDependency */ = { + D26A457C36225DE41C7BB4FD7A7FF254 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = GoogleAnalytics; - target = DACB20301113D16B776F458649C04D75 /* GoogleAnalytics */; - targetProxy = F0FC023A7FAA25251FF855FDF3DF3B78 /* PBXContainerItemProxy */; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = FBBD79508378F74FDD48FDE8FBD95CA8 /* PBXContainerItemProxy */; }; - E2228131F0C84FB7D482CB8B6B8F7880 /* PBXTargetDependency */ = { + D6B9451245EC7F755751840A10706B3B /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SwiftLint; - target = 9297674709A684A35778E46A8DD2FBF1 /* SwiftLint */; - targetProxy = 95CBF8E05B1C8C21922F46385C8913AD /* PBXContainerItemProxy */; + name = Protobuf; + target = 470FE31978DC918618A329D8B55C85FF /* Protobuf */; + targetProxy = 265B4CB516E1900A62F53357B2801D7D /* PBXContainerItemProxy */; }; - EE523C5AA43982C6705936C26BE33556 /* PBXTargetDependency */ = { + D6CCD2C4CEAD112F1B79C0511A89B945 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Crashlytics; - target = 56C65DE44367A2F21D49CA08AFC9FB3B /* Crashlytics */; - targetProxy = 085642005FA342665658867CF888B052 /* PBXContainerItemProxy */; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 0E252FBA5043E82AE7E96DA6EB172D5A /* PBXContainerItemProxy */; + }; + DC9B574DFA929B605978935F3BDB7CD8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 650053CB0020B8878A2D404A11BA8849 /* PBXContainerItemProxy */; + }; + DF830C96531680BABA48C2DEBA893DA2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = A0D8BA7AAAA886E42762C6361B9E93C5 /* PBXContainerItemProxy */; + }; + E1D1984FE10DD52FB5F2B2F12B34CD23 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = BA9CC50F725C6CC259A91562DDF28E28 /* PBXContainerItemProxy */; }; - EF971051DAD5EA10088D0143CE95CC26 /* PBXTargetDependency */ = { + E4A173EB136AA75485C7DD75F12B1475 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = KeychainAccess; - target = CCAB7541106C9A08F37141B4E6BABE82 /* KeychainAccess */; - targetProxy = 4D08AA0D173311D87B23B36F15F881C9 /* PBXContainerItemProxy */; + target = 615C831BCE925ED486B225B87E44926D /* KeychainAccess */; + targetProxy = 2643B7A0DCE050B7ED6CFA33DA0F6891 /* PBXContainerItemProxy */; }; - F45F97E2AC9D9901B0B10D817F5D194C /* PBXTargetDependency */ = { + ECCC460C69DA33393BD4B7A85952E4A2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Fabric; - target = E28CCDDA0BCE0276CB18E6AE6E42CC00 /* Fabric */; - targetProxy = B5A935E1584EE3E560B5CE58A9AEC03B /* PBXContainerItemProxy */; + name = Swiftilities; + target = E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */; + targetProxy = 43F7D12D0CBAC174D94F813DCDD5FCB4 /* PBXContainerItemProxy */; }; - FB72D79D5C32519D1D945170633EEE4D /* PBXTargetDependency */ = { + F0793E63BFABF823AEB6F71A3674DAE1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = BonMot; - target = 2C73C7C87E96DD68B751D61C1033C498 /* BonMot */; - targetProxy = 3916A6D013B15592701353B07264AEDC /* PBXContainerItemProxy */; + name = Anchorage; + target = 4607A9D579EE69C57F52971930107170 /* Anchorage */; + targetProxy = 79EEB88422FF194A2426408E288FCAA8 /* PBXContainerItemProxy */; }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 01518A20EC78065AAF3735DCA663CEAD /* AppStore */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = AppStore; + F7AB0C563506FE1FE6520F4C7180C61E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Swiftilities; + target = E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */; + targetProxy = 92AABBA7207468A376E84C3CAB584DF1 /* PBXContainerItemProxy */; }; - 039EE3DB7B81592FA54E996A2FA0ADA2 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; + F9A75F4BC4D33D1F83CBE160AE2D088A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = D10A23904F9F6203C441116CC0642596 /* PBXContainerItemProxy */; + }; + F9BEA3D05D836C128E1EDBBAFDABF6FA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Alamofire; + target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */; + targetProxy = 2871C78E72BACE3957C7839A26C5C9E2 /* PBXContainerItemProxy */; + }; + FB6BFA54D8E0043795CCFBF57526DAC9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = 39C2E1ACB757D961A3B5FA5055DBDB7A /* PBXContainerItemProxy */; + }; + FE3F8C74A60E5614770271527A3085D9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sourcery; + target = 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */; + targetProxy = 9DE5315A218DF3035FAB4B2C9C4D11CB /* PBXContainerItemProxy */; + }; + FE817F57A0DB193392689548BF3A3052 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalyticsInterop; + target = D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */; + targetProxy = 0C1025B53BD27B110B05E793A41AAC91 /* PBXContainerItemProxy */; + }; + FEB053648A54BC05E6A6BD49CB6EFFB8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 635675962B01177CB052EE57060E9175 /* PBXContainerItemProxy */; }; - 03D42C232D85D8E95BF9E396A0593861 /* Release */ = { +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00EB2E82A5B0B8A56724F99E9E52E4D1 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -2623,28 +5076,27 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; - PRODUCT_MODULE_NAME = SimulatorStatusMagic; - PRODUCT_NAME = SimulatorStatusMagic; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 0B043566A28F12499EF87ECB81EFCBD4 /* Sprint */ = { + 0254BAE7CE7FF9132CED803AB907108A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -2655,28 +5107,27 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; - PRODUCT_MODULE_NAME = KeychainAccess; - PRODUCT_NAME = KeychainAccess; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Debug; }; - 0F4EC60DB5AAAD234EFA6B150F815685 /* Sprint */ = { + 039EE3DB7B81592FA54E996A2FA0ADA2 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -2686,12 +5137,42 @@ TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; - name = Sprint; + name = Release; }; - 109ED2271BBCCD476CADA3B45E2DCFB5 /* AppStore */ = { + 04A03498AB90701059293AFCA227A006 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 04A2E9C489820651DDD7EBB81053B7F6 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 04B18C7BB734A96B78663C803082150E /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 518BACD57DCD1AA45BE9270B8C5CF1B5 /* Pods-PRODUCTNAME.sprint.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2701,43 +5182,32 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; - PRODUCT_MODULE_NAME = Alamofire; - PRODUCT_NAME = Alamofire; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; - }; - 11F9092E77544F230B698CEBAE36F056 /* AppStore */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = AppStore; + name = Sprint; }; - 124A4C27A8874D4DF4D59D2CA1F4CB37 /* Release */ = { + 0713FE5CA23092328690CD5EB985282E /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */; + baseConfigurationReference = 3CE8A623704EA768F5F5576533B75CC4 /* Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2747,28 +5217,29 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; - PRODUCT_MODULE_NAME = OHHTTPStubs; - PRODUCT_NAME = OHHTTPStubs; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = AppStore; }; - 14E8B325593A0C460C587178B7C532D0 /* Release */ = { + 0D8464153D08FF29E320719CA18CC762 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -2780,9 +5251,23 @@ }; name = Release; }; - 15DD46D8FB63AE5E9C384C5FC1AC0BF9 /* Sprint */ = { + 0F25A9D4FB36C7AEE76E082640AEB849 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0F4EC60DB5AAAD234EFA6B150F815685 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -2794,9 +5279,9 @@ }; name = Sprint; }; - 18463BAE2F5013993ACEBFF24111478A /* Develop */ = { + 1051691A092C7F9BF7A92E2499457D71 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -2824,76 +5309,14 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Develop; - }; - 196DFA3E4A09A28224918543529A1885 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; + name = Release; }; - 19F5B224A1D205A203BB03C0E799AD0A /* AppStore */ = { + 1199DB3A26F46619A4FCEC8A16240B6F /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */; + baseConfigurationReference = FA50610602A727B99D7294CFF81CC8E8 /* Pods-Services.sprint.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2903,30 +5326,59 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; - PRODUCT_MODULE_NAME = Swiftilities; - PRODUCT_NAME = Swiftilities; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; + name = Sprint; + }; + 11F9092E77544F230B698CEBAE36F056 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; name = AppStore; }; - 1AF58D3DF19E64ED279DA487BB8CFDFE /* Develop */ = { + 12B0D6060B6FDC7B09FFA077EAF0B6D9 /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = ""; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 144971CF95B2CD5FCA86ABF5BADCB555 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -2935,14 +5387,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; - PRODUCT_MODULE_NAME = BonMot; - PRODUCT_NAME = BonMot; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -2952,46 +5404,25 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = Sprint; }; - 1BA6802F68C6A222C2B5DF2500B1CC37 /* Sprint */ = { + 14E8B325593A0C460C587178B7C532D0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 88BA0595C84DF09AE03104A4BDD671A8 /* Pods-PRODUCTNAME.sprint.xcconfig */; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; - SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Release; }; - 204A727D957819558F27765EE2A2A1D6 /* AppStore */ = { + 159D225BF64246DF8997FEA3CA3EC301 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3002,14 +5433,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; - PRODUCT_MODULE_NAME = OHHTTPStubs; - PRODUCT_NAME = OHHTTPStubs; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -3019,24 +5450,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; - }; - 237FA8EFEFE9C41211C561C99BC193AC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; + name = Release; }; - 27D408BB1211933A0502CF1CEE2BF333 /* Release */ = { + 17CDC4C0F8D77EC8C6301E0F603D7B15 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3047,14 +5465,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; - PRODUCT_MODULE_NAME = KeychainAccess; - PRODUCT_NAME = KeychainAccess; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -3064,40 +5482,13 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; - }; - 29156109D6DAA3216C00BE3D56C4CD25 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 3081CFAE229FA4D87A8A3E02E6DCA7CE /* Develop */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; name = Develop; }; - 30B07E7F93DAA4745111CCFDCD5C508E /* Sprint */ = { + 18CA8C893BCBE6F8D77C5A5AEE2E3C5A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3107,40 +5498,27 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; - PRODUCT_MODULE_NAME = Swiftilities; - PRODUCT_NAME = Swiftilities; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; - }; - 31C38884615A92804F933F54CD7A8234 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; name = Release; }; - 32DF797FC2BA977E48213B2D2905F94E /* AppStore */ = { + 196DFA3E4A09A28224918543529A1885 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -3173,13 +5551,16 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; + DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_APP_STORE=1", + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -3189,52 +5570,35 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MTL_ENABLE_DEBUG_INFO = NO; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; - name = AppStore; + name = Debug; }; - 32EB45EA865F25FCF1C659C3E2714957 /* AppStore */ = { + 1B568D5E7B586B33C7A6283DFCD7471A /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; - PRODUCT_MODULE_NAME = KeychainAccess; - PRODUCT_NAME = KeychainAccess; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; - name = AppStore; + name = Develop; }; - 35D1535C582777BDAD568E2FB127C674 /* AppStore */ = { + 1B8E2F83D29A7E155F9C0D7667985900 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -3242,14 +5606,15 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = AppStore; + name = Debug; }; - 3620B4971E748FE887C6F7BFEE5E0876 /* Develop */ = { + 1C8A0A6F4C5F5B881F1EFBF4871CD760 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */; + baseConfigurationReference = FCBFF9345F652100273AE93760F66435 /* Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3259,18 +5624,19 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; - PRODUCT_MODULE_NAME = Swiftilities; - PRODUCT_NAME = Swiftilities; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -3278,9 +5644,9 @@ }; name = Develop; }; - 36DED9CF34365C7C4704E68F088A1C7A /* AppStore */ = { + 1CFF61CD09FAF75F0BC682385BFCFFF6 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3291,28 +5657,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; - PRODUCT_MODULE_NAME = BonMot; - PRODUCT_NAME = BonMot; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; + name = Develop; }; - 37C295695CB5D8C246E57249CDED97A4 /* Develop */ = { + 1EE499CAA9B9A581F734CFAF6A89AE21 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3342,9 +5708,9 @@ }; name = Develop; }; - 3D01E6FDCA9535F7F0C0878E2805DA6F /* Develop */ = { + 1EF59DD9196C67C2E74F889C3D4F0688 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 76CC1EB38705E8C45784419E12627B8B /* Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig */; + baseConfigurationReference = 4C3439A40A51D1DD58761BACB9331DD2 /* Pods-PRODUCTNAME.develop.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3357,12 +5723,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -3377,9 +5743,23 @@ }; name = Develop; }; - 3E5452AB2D04004B314626A29B4AAF3B /* Sprint */ = { + 2100E3A23E09BC4C1BF0048C9EAD2668 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2822158D7FB1BA237200334E1B16A5C6 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3390,14 +5770,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; - PRODUCT_MODULE_NAME = OHHTTPStubs; - PRODUCT_NAME = OHHTTPStubs; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -3407,11 +5787,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Develop; }; - 3F7576268B1B7301AB1C0277B735D231 /* Sprint */ = { + 2A7F38D1EF8B29D489C3832351159F23 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -3423,12 +5803,10 @@ }; name = Sprint; }; - 42DE9E57338CCC305496EBDD26212F8A /* Debug */ = { + 2C0B45A6DDB4DBDF13F8CE92C38F53C1 /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E172436BEA1AA48D80B4772E292D7D6F /* Pods-Services.debug.xcconfig */; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3438,31 +5816,57 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = AppStore; }; - 44F0B896D02B2BE4D3AB1DD26520E37B /* Sprint */ = { + 2C6C1ADA1F07A8A724FC6FA8DE0D080C /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DD20F29EDEBA60AED25F95B2CE422567 /* Pods-Services.sprint.xcconfig */; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 2C7C989247E976CB9C619585E7ED8A3D /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 2E0BAC58EBC4FC3F5FD6C17B54A79FCE /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3472,27 +5876,99 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Release; }; - 450810C364F1E1DDF83105C03CE8BC36 /* Develop */ = { + 2E1070759DFCEAE5DBC3D05A79D21818 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 2EBE7AF5528F4B0A2979A4F75E2B7455 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3050D30F799954B1E665C3A7680DD3B0 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 3081CFAE229FA4D87A8A3E02E6DCA7CE /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 32DF797FC2BA977E48213B2D2905F94E /* AppStore */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -3531,7 +6007,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEVELOP=1", + "POD_CONFIGURATION_APP_STORE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -3550,43 +6026,25 @@ SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; - name = Develop; + name = AppStore; }; - 474A0C0DEA0264E9C60832E18A81AEBD /* Develop */ = { + 35AA0B11D35AF3095628DA85C865C8F9 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; - PRODUCT_MODULE_NAME = OHHTTPStubs; - PRODUCT_NAME = OHHTTPStubs; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = Release; }; - 47EBFCBB800FC5C74BF785A4130ACFBF /* Debug */ = { + 364397E9C482719315F8047008C221D2 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DA0914676ACB3881C960293BB680AECD /* Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig */; + baseConfigurationReference = 1358F7B95EC32C0D0017CE9DBF481067 /* Pods-Services.develop.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3599,12 +6057,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -3613,14 +6071,15 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Develop; }; - 4AFE1632DF385493AAF0959EAB15A6FB /* Debug */ = { + 39AF457727CE54F1468C1931870EE8D7 /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE0BA8780FDAFCFC6F2717C5D791F482 /* OHHTTPStubs.xcconfig */; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3631,56 +6090,45 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; - PRODUCT_MODULE_NAME = OHHTTPStubs; - PRODUCT_NAME = OHHTTPStubs; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; - }; - 500782DB6B726869B3DF62BC3C4A561B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; + name = AppStore; }; - 585C9BE0ACBC128D7D9DC86D93622950 /* Develop */ = { + 3B2882C18947648D49623DE63CD7878B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; SDKROOT = iphoneos; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; }; - name = Develop; + name = Release; }; - 586C276C8E7B242877EFEAB1B7D121C1 /* Release */ = { + 3BC5A964067AEDB034176E8C2BB6E7FF /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3690,19 +6138,18 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -3710,9 +6157,9 @@ }; name = Release; }; - 5ED2FE244707B468C74A660A21E29029 /* AppStore */ = { + 408553D5662ECD01C20BEEAE8476A0C7 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3723,44 +6170,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; - PRODUCT_MODULE_NAME = Anchorage; - PRODUCT_NAME = Anchorage; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; - }; - 63ECAB3994BFB9748CC59B38CADC7DB3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; name = Debug; }; - 65E229AD454727B1F65EAF577AD698CA /* AppStore */ = { + 41270F5C2928C3228E603B006F90F1CC /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2C2CF3EDAF2544698EB98DE619346902 /* Pods-Services.appstore.xcconfig */; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3770,72 +6201,102 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; + name = Debug; }; - 6695784FCCABB730014805A0EB284E5C /* Develop */ = { + 42E49BF53D9157BB9344A2CC526BACC5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Develop; + name = Debug; }; - 669A20526B876F22A3CB86ACBB325D48 /* Sprint */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Sprint; - }; - 69676CF0BD63662A543E125C1388DA3B /* Sprint */ = { + 450810C364F1E1DDF83105C03CE8BC36 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEVELOP=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; }; - name = Sprint; + name = Develop; }; - 69A94AF15779DDF0A8F671C5CF8A303C /* Sprint */ = { + 49766F900A5C72F44F481929BA94E8DD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3845,31 +6306,30 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; - PRODUCT_MODULE_NAME = Anchorage; - PRODUCT_NAME = Anchorage; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Release; }; - 6A9265256B4D83B02667E20268CE175A /* Develop */ = { + 499E3B22BACADD3B8477C76F94E244B6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B4E5336742C14FD6B50FD57C94F7E2EF /* Pods-PRODUCTNAME.develop.xcconfig */; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3879,32 +6339,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = Debug; }; - 6AD3F3CF64CBCA852733202742022EA9 /* Debug */ = { + 4E20B0FBC288B4FD517A0DF3FB456E2C /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F8EB17459DA65ED2256E7DD16A25905C /* Pods-PRODUCTNAME.debug.xcconfig */; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3914,28 +6370,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = AppStore; }; - 79049A6A707E3D41D64C015FED8FAEF8 /* Release */ = { + 509B26019E80E3850DC661C59B808AEC /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -3943,16 +6399,13 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Release; + name = Debug; }; - 7AFA7D24954A48C5DE8B631BDFB7DE6B /* Sprint */ = { + 53551413403BE972D3E8493F09D2C8FD /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 29EF59452D21EA57CF6157AFAE72F043 /* Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig */; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3962,57 +6415,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; - }; - 89556E0B18C1462D9C8452E100F1A91A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 8A5F06731CAABDB55C74C2797ED7ACC8 /* AppStore */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; name = AppStore; }; - 8A9AFA9B1BB7609AE809BDF2B71BCCB0 /* AppStore */ = { + 550B6A298227661823F1F5C8EAC12E56 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4023,14 +6447,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; - PRODUCT_MODULE_NAME = SimulatorStatusMagic; - PRODUCT_NAME = SimulatorStatusMagic; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -4040,11 +6464,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; + name = Develop; }; - 8CB18B56F11C8D3DDE058D63AB67759A /* Debug */ = { + 552B962A72956A32E1115D1EABC2E9F5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4055,27 +6479,27 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; - PRODUCT_MODULE_NAME = Swiftilities; - PRODUCT_NAME = Swiftilities; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 954B6FF531D2DA317662393A0241E9F3 /* Release */ = { + 55D765C25ECE04A06B8472EF8DFC9DFD /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 39AF5A4F1AD61032BC907C0AC0B34151 /* Swiftilities.xcconfig */; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4103,25 +6527,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; - }; - 96C74D5221D5814C2CE57E69013C3960 /* AppStore */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9447E87524BF9DDE37BEA84464E38ED2 /* Fabric.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; name = AppStore; }; - 97E80891349D82BB1AAEEF0DB8F59076 /* Develop */ = { + 56D6E34BB3BA305D4FA7DE8351D15A46 /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4132,14 +6542,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; - PRODUCT_MODULE_NAME = KeychainAccess; - PRODUCT_NAME = KeychainAccess; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -4149,11 +6559,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = AppStore; }; - 9EC75EA43BA76F31EEB1BB7A7457B93D /* Debug */ = { + 5E16DF94949DE370FF8D05B1E045B422 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4164,29 +6574,42 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; - PRODUCT_MODULE_NAME = BonMot; - PRODUCT_NAME = BonMot; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; + name = Sprint; + }; + 5F5BCFAB1070EDB4201DFE7442682AE2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; name = Debug; }; - 9EFD5255CC75346853858C253083DBB7 /* Release */ = { + 61AD3E65B684B8E73656F0D56E018E29 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4196,13 +6619,552 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; - OTHER_LDFLAGS = ""; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 633FC423F2340EFA2707DC27384F9758 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6359B27DDFBAAE66820844B7D3BF1FA5 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 63ECAB3994BFB9748CC59B38CADC7DB3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6695784FCCABB730014805A0EB284E5C /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 669A20526B876F22A3CB86ACBB325D48 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 68A8D49864B3832FE56A43ED9B1B123F /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 6962A61309DC47EF9A575651A2398BE5 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 69676CF0BD63662A543E125C1388DA3B /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 6B730C2AD0DC9F84451A95E0ED36711E /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 6F7C956FBBCA91ECDF34F5C9E200B32F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 7020CBA8E19C4B6CF917293F57A0F527 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 71D5922172D4BD46D1AC0DD998152A48 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 726AAC41D2598F544BCCD63B8F121641 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 300E24828164112EB400CCFD1E0D55B9 /* Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 74A377298A7D8A87145937AF5D80DCE8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 74F5C40245ED34AFFCCF455D62178E4D /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 767863B65D92FB2CB2EE44143C7E2DFC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 76B98C1F7279585A3DD4518B7A92A3F3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7786C4C4E9915070055DB93D1913AC43 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 787131EB6F6B472B14334B443B8ABEFE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 78C9F0FA9EF8EDD145018C7274250F50 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7A77DF826D098FF294E4863DAE59DCF5 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 7ED7514A62123D5D92584EA8C9C37C39 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8CC134AECB569C629CF74E270D3E8FC3 /* Pods-PRODUCTNAME.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; + OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; @@ -4210,42 +7172,714 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7F5387FAE75904C8004C212967CB3D9E /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 85AD63334D8D13A60DFE0BB1071985A1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 88BE0DFE71CC7168CFCC5C94FD68FBAF /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Sprint; + }; + 88F1D88DE44D2B31391FB31F87F5420B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 897DF11BAB21990629273F4ED92C4BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8D4E8064A6E1AE1BC3059CDADAC6099B /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 8F096FFE8BE74F303E264B15215402F7 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 90EE269E3843AE0436AE918C0F54059F /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 92961265545DD48C54C580534E52CF68 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 953BC77CB9790C62A92DF0A2929FF3C5 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 96C74D5221D5814C2CE57E69013C3960 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 9965E55FC4DECB0117079BD67CF8878D /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 9C70C99294CC907784B8B046DEE5ADD0 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 9D93C1F0F78F34A3C48E2A6B55563C65 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9DA51A607CE00DD6264E22148850D773 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; + }; + name = AppStore; + }; + 9F69C0A0AB91255C0692BB69E36686D0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 9F8B0E054D88C9FC8917BBFBC1360620 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A041F186FE50D9877B5819916FDF0566 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + A06DBFB160B14C3FA503AA03B81A725E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A5A6C84A12A24B5A0FE3506327BC97B0 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + A68E4364E8E879D0CCC3B774083C68DF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + AA7077CCF0F64B5EA73E673F2B07AFD2 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + AA7597AE20A25CD48F28517DA043BBD2 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + AAA519652BFF7D297098BD1231DEC00E /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Develop; }; - A3EAEDB5C113A650F51E3274102BB79F /* Develop */ = { + ABCAE6CDB3895468DB3C480224431DFC /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FD718C56F06AD6E7A6B3E4C39837F8AE /* SwiftLint.xcconfig */; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; - name = Develop; + name = AppStore; }; - AA2EE7111DE5DF647A8EC683E63BD94D /* Debug */ = { + AD8485FE4FD0FA44414D0D3ECB167981 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E8EA99F7CEC3433FA7D534360BFDF3FF /* SwiftGen.xcconfig */; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Sprint; }; - ABCAE6CDB3895468DB3C480224431DFC /* AppStore */ = { + AE124D04BF3E399310B7C68FF9701F9A /* Sprint */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_SPRINT=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Sprint; + }; + AF1DF8E0128E062AE69D83B2532AAD7E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -4253,11 +7887,10 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = AppStore; + name = Debug; }; - AE124D04BF3E399310B7C68FF9701F9A /* Sprint */ = { + B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -4296,7 +7929,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_SPRINT=1", + "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -4315,84 +7948,209 @@ SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; + name = Release; + }; + B22756789FA9D2660AA73FDE4B8229FE /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + B35D9CD99D8A25AB4414B3B709AC720A /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + B44E2B38C771C5A2C004CA70C1C2B036 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + B842C542B2D62DF3B418AA5CF63FC75E /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + BECCEE3147E15EC5BB626D63AEDA427C /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + C0CC21FC535B013F47BA834C17EDE971 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + C116202B204AD641474621E4DD1EFD8C /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; name = Sprint; }; - AF1DF8E0128E062AE69D83B2532AAD7E /* Debug */ = { + C34442325BC613212BE360E9A1B287C0 /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = AppStore; }; - B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */ = { + C3EDB0EF10720D252471E621F18A22C6 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; name = Release; }; - B0FED054A7E207C28B6A0B875DF71DDE /* Sprint */ = { + C79E87935912A6EDADF557045121C2FB /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4403,28 +8161,27 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; - PRODUCT_MODULE_NAME = BonMot; - PRODUCT_NAME = BonMot; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Debug; }; - C190BF4BE28E61A82B56CD58CCFF247D /* Sprint */ = { + C88F9D7AE9397281737BE3E4368E6A2E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4435,14 +8192,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; - PRODUCT_MODULE_NAME = SimulatorStatusMagic; - PRODUCT_NAME = SimulatorStatusMagic; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -4452,25 +8209,24 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = Release; }; - C3EDB0EF10720D252471E621F18A22C6 /* Release */ = { + D08D01F4ECD4EACABAFFDA7D8BF8C650 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2F8CB53AD1B1419A75469497E433A2EE /* Instabug.xcconfig */; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Release; + name = Debug; }; - C51FDDA714D96323E9F9DE454B9BBDAC /* Debug */ = { + D145A3500A16BD3C2F77656477C0973A /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4481,27 +8237,42 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; - PRODUCT_MODULE_NAME = Alamofire; - PRODUCT_NAME = Alamofire; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = AppStore; + }; + D1529A02A55F2EB4E938DAF6F814198A /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; }; - C88EFD33AEC15D0F341751F5B254FB26 /* Release */ = { + D35CA734DD619ED347BD1DF725F3EC63 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4512,14 +8283,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; - PRODUCT_MODULE_NAME = Anchorage; - PRODUCT_NAME = Anchorage; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -4529,10 +8300,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Sprint; }; - CB3305642C33E1E41F975215F72BE47C /* Release */ = { + D43D4960BF9B5B2EE70F2E74AC781C23 /* AppStore */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 1987EE9FAD1DBEC74F2716EA5DC6B2D0 /* Pods-Services.appstore.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -4545,12 +8317,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -4563,11 +8335,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = AppStore; }; - CB85697C5DCBBA7038F18264C80D9F03 /* Debug */ = { + D507D5924E1956DD46D4CEA4A90B6809 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C64C4E3A4209841579EBAEF53ECBB2F7 /* KeychainAccess.xcconfig */; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4578,82 +8350,60 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; - PRODUCT_MODULE_NAME = KeychainAccess; - PRODUCT_NAME = KeychainAccess; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; - }; - CC3E078A54B67C6BFDB72354AB4A5DA8 /* Sprint */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Sprint; - }; - CCB2C379C166D909E560ECB344ECB7A3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - CD5DBD1689ACB251129A9F3832BB66DF /* Sprint */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; name = Sprint; }; - D38640D2B4D77E7E47A79F0F91EE109C /* Develop */ = { + D793ADAD0EC3994198BEAC0EFD3A4201 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = Release; }; - D3C43F12005E9F42072E5D6AFB71C529 /* Develop */ = { + D799CBBECD2761D3D5D077351D4506EB /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 763EA71849BAFD4F80AE0913CD8AEB09 /* Pods-Services.develop.xcconfig */; + baseConfigurationReference = C4B85119F40EE2D53CF9459420F29B53 /* Pods-PRODUCTNAME.appstore.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -4666,12 +8416,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -4684,12 +8434,13 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = AppStore; }; - D90331BC285A6E975EAF4BB77EFDD3BB /* Debug */ = { + DAAA5A6195EA66DEF295EFDB8229C517 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765689D08C97A8055B9418702EE75FEB /* SimulatorStatusMagic.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4699,28 +8450,60 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; - PRODUCT_MODULE_NAME = SimulatorStatusMagic; - PRODUCT_NAME = SimulatorStatusMagic; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DC8D8A01840CF56E0D9F579AE919ED3D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DE31AB1501D6E1FCABBA192529BE687A /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = Develop; }; - E0CD56070245862C6501B04905B5909D /* Release */ = { + E147BD630EF0E4454A1C5C8DA27B8289 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */; + baseConfigurationReference = 7B31944D9854B90AB402DAEBC2714BCB /* Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4730,28 +8513,29 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; - PRODUCT_MODULE_NAME = Alamofire; - PRODUCT_NAME = Alamofire; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Sprint; }; - E18B836048D8B7CED50153883D7BA21E /* Develop */ = { + E29E38B22BBE23E680601EB9B01F8761 /* Sprint */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4762,14 +8546,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; - PRODUCT_MODULE_NAME = Anchorage; - PRODUCT_NAME = Anchorage; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -4779,11 +8563,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Develop; + name = Sprint; }; - E4FC8B7CB4BD92EB6DDF9AF09564096B /* Debug */ = { + E4B02B37D44325E20D374DCD3C7C229B /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3F10A426D230755BB86E86DCCDDF36D3 /* Anchorage.xcconfig */; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4794,27 +8578,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; - PRODUCT_MODULE_NAME = Anchorage; - PRODUCT_NAME = Anchorage; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Develop; }; - E8D6C9DBFC70F8E2CFF9D81BBF44369D /* Develop */ = { + E6F928BAAFE49B0BFF922CB775A36876 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C62E6993FB2715E5D81612BB3E0958FD /* Sourcery.xcconfig */; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -4826,9 +8611,9 @@ }; name = Develop; }; - EA54336624E67F8E2ACD8D9E659395B4 /* Release */ = { + EA88E206F53F5B0170EA50A9EBDAAF07 /* AppStore */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B7A7E024E6A5A7938669C60B33E3DE33 /* BonMot.xcconfig */; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4839,46 +8624,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; - PRODUCT_MODULE_NAME = BonMot; - PRODUCT_NAME = BonMot; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - F04546DB60ABCED0782EB17FDAEF50C8 /* Sprint */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8758416EF02EC5608142630EC9A24463 /* Alamofire.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; - PRODUCT_MODULE_NAME = Alamofire; - PRODUCT_NAME = Alamofire; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; @@ -4888,11 +8641,11 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Sprint; + name = AppStore; }; - F330ABE5447C3B8163B50A33CD693F7B /* Debug */ = { + EBC0241E2EDBDD9DCB253CCC4A4C250F /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -4900,12 +8653,13 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = Develop; }; - F434EFA088FCD3B0215C8B9AB75D55EA /* AppStore */ = { + EE9B60D8F1FED00BC5D55D35C2B67C86 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 762B6EA59AD44657FC4F6F155EE84D81 /* Pods-PRODUCTNAME.appstore.xcconfig */; + baseConfigurationReference = 63202DA0FE6824272136B2EC50F9FB63 /* Pods-Services.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -4918,12 +8672,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -4932,18 +8686,58 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; + name = Debug; + }; + F0BB655AF6A9EBC59E21E9AD77EA7155 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; name = AppStore; }; - F454DF6347BF2B543FF2B8FE8E73F41F /* AppStore */ = { + F13196A4950243EBC6D7E5A7CE023F74 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3FA96E21CB7C709D604705CC1A70427A /* Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig */; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + F330ABE5447C3B8163B50A33CD693F7B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F8EE708210187D87C395FFAB338FB6D6 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4953,29 +8747,28 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = AppStore; + name = Develop; }; - F74C4D970A04E212732E451FF4FB1C40 /* AppStore */ = { + FC1A59A202CBA257ABFB40043E669367 /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A5476A23BA5813EF0CC67790944BB5D4 /* GoogleAnalytics.xcconfig */; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -4985,93 +8778,73 @@ TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; - name = AppStore; + name = Develop; }; - FC1A59A202CBA257ABFB40043E669367 /* Develop */ = { + FF90010BB3F5E1134B46DE5DA1CCB64E /* Develop */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8C3C8FB9A5F9520E05E8ABF62C9E026A /* Crashlytics.xcconfig */; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; SDKROOT = iphoneos; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; }; name = Develop; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 08E73384D62CB365E65493BF13FCEBF2 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 35D1535C582777BDAD568E2FB127C674 /* AppStore */, - 237FA8EFEFE9C41211C561C99BC193AC /* Debug */, - A3EAEDB5C113A650F51E3274102BB79F /* Develop */, - 89556E0B18C1462D9C8452E100F1A91A /* Release */, - 3F7576268B1B7301AB1C0277B735D231 /* Sprint */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 128428A69B6EB4E4F59D18E4910240F6 /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME-PRODUCTNAMETests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - F454DF6347BF2B543FF2B8FE8E73F41F /* AppStore */, - 47EBFCBB800FC5C74BF785A4130ACFBF /* Debug */, - 3D01E6FDCA9535F7F0C0878E2805DA6F /* Develop */, - 586C276C8E7B242877EFEAB1B7D121C1 /* Release */, - 7AFA7D24954A48C5DE8B631BDFB7DE6B /* Sprint */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 196370951A0DF83F84523C5518D80950 /* Build configuration list for PBXNativeTarget "Anchorage" */ = { + 0A1FEBE926726C9A3E064BDC1F0E7D33 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { isa = XCConfigurationList; buildConfigurations = ( - 5ED2FE244707B468C74A660A21E29029 /* AppStore */, - E4FC8B7CB4BD92EB6DDF9AF09564096B /* Debug */, - E18B836048D8B7CED50153883D7BA21E /* Develop */, - C88EFD33AEC15D0F341751F5B254FB26 /* Release */, - 69A94AF15779DDF0A8F671C5CF8A303C /* Sprint */, + F0BB655AF6A9EBC59E21E9AD77EA7155 /* AppStore */, + 2EBE7AF5528F4B0A2979A4F75E2B7455 /* Debug */, + 1B568D5E7B586B33C7A6283DFCD7471A /* Develop */, + DC8D8A01840CF56E0D9F579AE919ED3D /* Release */, + 2C6C1ADA1F07A8A724FC6FA8DE0D080C /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1DC2CF1023FFA0AB7BB266205EFFB20A /* Build configuration list for PBXAggregateTarget "Sourcery" */ = { + 0BD4EFF72DD4194F3E6290A1EAE82CBC /* Build configuration list for PBXAggregateTarget "Firebase" */ = { isa = XCConfigurationList; buildConfigurations = ( - 01518A20EC78065AAF3735DCA663CEAD /* AppStore */, - CCB2C379C166D909E560ECB344ECB7A3 /* Debug */, - E8D6C9DBFC70F8E2CFF9D81BBF44369D /* Develop */, - 29156109D6DAA3216C00BE3D56C4CD25 /* Release */, - CC3E078A54B67C6BFDB72354AB4A5DA8 /* Sprint */, + 3050D30F799954B1E665C3A7680DD3B0 /* AppStore */, + D08D01F4ECD4EACABAFFDA7D8BF8C650 /* Debug */, + EBC0241E2EDBDD9DCB253CCC4A4C250F /* Develop */, + 2100E3A23E09BC4C1BF0048C9EAD2668 /* Release */, + 8D4E8064A6E1AE1BC3059CDADAC6099B /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 27B1D85313010C4465E2E9963174D7DC /* Build configuration list for PBXNativeTarget "Swiftilities" */ = { + 14608CC6B8CF27B7AF9B3D5F5B6F8607 /* Build configuration list for PBXAggregateTarget "SwiftGen" */ = { isa = XCConfigurationList; buildConfigurations = ( - 19F5B224A1D205A203BB03C0E799AD0A /* AppStore */, - 8CB18B56F11C8D3DDE058D63AB67759A /* Debug */, - 3620B4971E748FE887C6F7BFEE5E0876 /* Develop */, - 954B6FF531D2DA317662393A0241E9F3 /* Release */, - 30B07E7F93DAA4745111CCFDCD5C508E /* Sprint */, + C34442325BC613212BE360E9A1B287C0 /* AppStore */, + 9F69C0A0AB91255C0692BB69E36686D0 /* Debug */, + A5A6C84A12A24B5A0FE3506327BC97B0 /* Develop */, + 7020CBA8E19C4B6CF917293F57A0F527 /* Release */, + C116202B204AD641474621E4DD1EFD8C /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2A5785C21CA61197EDDD1FE2EB0000F6 /* Build configuration list for PBXNativeTarget "SimulatorStatusMagic" */ = { + 1B3AA62DD852E489C6FA81F9BAE7F98C /* Build configuration list for PBXNativeTarget "OHHTTPStubs" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8A9AFA9B1BB7609AE809BDF2B71BCCB0 /* AppStore */, - D90331BC285A6E975EAF4BB77EFDD3BB /* Debug */, - 18463BAE2F5013993ACEBFF24111478A /* Develop */, - 03D42C232D85D8E95BF9E396A0593861 /* Release */, - C190BF4BE28E61A82B56CD58CCFF247D /* Sprint */, + B22756789FA9D2660AA73FDE4B8229FE /* AppStore */, + 897DF11BAB21990629273F4ED92C4BE5 /* Debug */, + 90EE269E3843AE0436AE918C0F54059F /* Develop */, + A68E4364E8E879D0CCC3B774083C68DF /* Release */, + 5E16DF94949DE370FF8D05B1E045B422 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5088,6 +8861,18 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 47242F938FAF8F33076BEC83B73F1607 /* Build configuration list for PBXNativeTarget "Alamofire" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 71D5922172D4BD46D1AC0DD998152A48 /* AppStore */, + 41270F5C2928C3228E603B006F90F1CC /* Debug */, + 1EE499CAA9B9A581F734CFAF6A89AE21 /* Develop */, + 159D225BF64246DF8997FEA3CA3EC301 /* Release */, + D35CA734DD619ED347BD1DF725F3EC63 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -5100,50 +8885,98 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4A64146D9987C769A06B164ECC751636 /* Build configuration list for PBXNativeTarget "KeychainAccess" */ = { + 4964BEA93FE393CBB81F0EB03B4B3C81 /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D799CBBECD2761D3D5D077351D4506EB /* AppStore */, + 7ED7514A62123D5D92584EA8C9C37C39 /* Debug */, + 1EF59DD9196C67C2E74F889C3D4F0688 /* Develop */, + 18CA8C893BCBE6F8D77C5A5AEE2E3C5A /* Release */, + 04B18C7BB734A96B78663C803082150E /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 590CEAC43BDDFAA9598150F9D23A62A1 /* Build configuration list for PBXAggregateTarget "FirebaseAnalyticsInterop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8F096FFE8BE74F303E264B15215402F7 /* AppStore */, + 1B8E2F83D29A7E155F9C0D7667985900 /* Debug */, + D1529A02A55F2EB4E938DAF6F814198A /* Develop */, + 74A377298A7D8A87145937AF5D80DCE8 /* Release */, + 2A7F38D1EF8B29D489C3832351159F23 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 615A1A40348710AE156325FFE219FE30 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 12B0D6060B6FDC7B09FFA077EAF0B6D9 /* AppStore */, + 509B26019E80E3850DC661C59B808AEC /* Debug */, + E6F928BAAFE49B0BFF922CB775A36876 /* Develop */, + 35AA0B11D35AF3095628DA85C865C8F9 /* Release */, + 6962A61309DC47EF9A575651A2398BE5 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7C6BA1361CF9FA39E02D40A29E2613E3 /* Build configuration list for PBXNativeTarget "FirebaseMessaging" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BECCEE3147E15EC5BB626D63AEDA427C /* AppStore */, + 408553D5662ECD01C20BEEAE8476A0C7 /* Debug */, + F8EE708210187D87C395FFAB338FB6D6 /* Develop */, + C88F9D7AE9397281737BE3E4368E6A2E /* Release */, + 953BC77CB9790C62A92DF0A2929FF3C5 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 860FD77954D8865C1B7965B630EFD07E /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME-PRODUCTNAMETests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 32EB45EA865F25FCF1C659C3E2714957 /* AppStore */, - CB85697C5DCBBA7038F18264C80D9F03 /* Debug */, - 97E80891349D82BB1AAEEF0DB8F59076 /* Develop */, - 27D408BB1211933A0502CF1CEE2BF333 /* Release */, - 0B043566A28F12499EF87ECB81EFCBD4 /* Sprint */, + 0713FE5CA23092328690CD5EB985282E /* AppStore */, + 726AAC41D2598F544BCCD63B8F121641 /* Debug */, + 1C8A0A6F4C5F5B881F1EFBF4871CD760 /* Develop */, + 49766F900A5C72F44F481929BA94E8DD /* Release */, + E147BD630EF0E4454A1C5C8DA27B8289 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 53C2FC4108B64D3730F1FDD3C9662622 /* Build configuration list for PBXAggregateTarget "GoogleAnalytics" */ = { + 991E43F74ED979CF133D44C61CD0896E /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */ = { isa = XCConfigurationList; buildConfigurations = ( - F74C4D970A04E212732E451FF4FB1C40 /* AppStore */, - 500782DB6B726869B3DF62BC3C4A561B /* Debug */, - D38640D2B4D77E7E47A79F0F91EE109C /* Develop */, - 79049A6A707E3D41D64C015FED8FAEF8 /* Release */, - CD5DBD1689ACB251129A9F3832BB66DF /* Sprint */, + 2C7C989247E976CB9C619585E7ED8A3D /* AppStore */, + 633FC423F2340EFA2707DC27384F9758 /* Debug */, + DE31AB1501D6E1FCABBA192529BE687A /* Develop */, + 9D93C1F0F78F34A3C48E2A6B55563C65 /* Release */, + 7A77DF826D098FF294E4863DAE59DCF5 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8A987AD8034C7D3591A04B28614AB4DD /* Build configuration list for PBXNativeTarget "Pods-PRODUCTNAME" */ = { + 994CC284732864C1FB83DEFEECB2939B /* Build configuration list for PBXNativeTarget "Protobuf" */ = { isa = XCConfigurationList; buildConfigurations = ( - F434EFA088FCD3B0215C8B9AB75D55EA /* AppStore */, - 6AD3F3CF64CBCA852733202742022EA9 /* Debug */, - 6A9265256B4D83B02667E20268CE175A /* Develop */, - CB3305642C33E1E41F975215F72BE47C /* Release */, - 1BA6802F68C6A222C2B5DF2500B1CC37 /* Sprint */, + D145A3500A16BD3C2F77656477C0973A /* AppStore */, + C79E87935912A6EDADF557045121C2FB /* Debug */, + AAA519652BFF7D297098BD1231DEC00E /* Develop */, + 3BC5A964067AEDB034176E8C2BB6E7FF /* Release */, + AD8485FE4FD0FA44414D0D3ECB167981 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9B52E2818E288A284E7E71DE0DFE35C1 /* Build configuration list for PBXNativeTarget "Alamofire" */ = { + 99D1947D468DCEAA4431F1F95263DC3A /* Build configuration list for PBXNativeTarget "KeychainAccess" */ = { isa = XCConfigurationList; buildConfigurations = ( - 109ED2271BBCCD476CADA3B45E2DCFB5 /* AppStore */, - C51FDDA714D96323E9F9DE454B9BBDAC /* Debug */, - 37C295695CB5D8C246E57249CDED97A4 /* Develop */, - E0CD56070245862C6501B04905B5909D /* Release */, - F04546DB60ABCED0782EB17FDAEF50C8 /* Sprint */, + 4E20B0FBC288B4FD517A0DF3FB456E2C /* AppStore */, + 767863B65D92FB2CB2EE44143C7E2DFC /* Debug */, + 2822158D7FB1BA237200334E1B16A5C6 /* Develop */, + 6F7C956FBBCA91ECDF34F5C9E200B32F /* Release */, + E29E38B22BBE23E680601EB9B01F8761 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5160,14 +8993,26 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B21E9464DC37774B2AF91DCB9DDC930D /* Build configuration list for PBXAggregateTarget "SwiftGen" */ = { + A304035945DB998EEDDC0634D2BF9F26 /* Build configuration list for PBXNativeTarget "Swiftilities" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8A5F06731CAABDB55C74C2797ED7ACC8 /* AppStore */, - AA2EE7111DE5DF647A8EC683E63BD94D /* Debug */, - 585C9BE0ACBC128D7D9DC86D93622950 /* Develop */, - 31C38884615A92804F933F54CD7A8234 /* Release */, - 15DD46D8FB63AE5E9C384C5FC1AC0BF9 /* Sprint */, + 55D765C25ECE04A06B8472EF8DFC9DFD /* AppStore */, + 787131EB6F6B472B14334B443B8ABEFE /* Debug */, + AA7597AE20A25CD48F28517DA043BBD2 /* Develop */, + A06DBFB160B14C3FA503AA03B81A725E /* Release */, + 144971CF95B2CD5FCA86ABF5BADCB555 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B345AD1AAB27ADDC33CD59391F2A2578 /* Build configuration list for PBXAggregateTarget "Sourcery" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA7077CCF0F64B5EA73E673F2B07AFD2 /* AppStore */, + 5F5BCFAB1070EDB4201DFE7442682AE2 /* Debug */, + A041F186FE50D9877B5819916FDF0566 /* Develop */, + 0D8464153D08FF29E320719CA18CC762 /* Release */, + B35D9CD99D8A25AB4414B3B709AC720A /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5184,38 +9029,122 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C91FEE7F75C8B22125948B9539B454A3 /* Build configuration list for PBXNativeTarget "OHHTTPStubs" */ = { + C16269269CE2C3CF48FAFB11DDCA540B /* Build configuration list for PBXNativeTarget "GoogleUtilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 56D6E34BB3BA305D4FA7DE8351D15A46 /* AppStore */, + 61AD3E65B684B8E73656F0D56E018E29 /* Debug */, + 550B6A298227661823F1F5C8EAC12E56 /* Develop */, + D793ADAD0EC3994198BEAC0EFD3A4201 /* Release */, + 7786C4C4E9915070055DB93D1913AC43 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D99A31EFD5DABE8C08BD3F146933A31D /* Build configuration list for PBXNativeTarget "Anchorage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EA88E206F53F5B0170EA50A9EBDAAF07 /* AppStore */, + 552B962A72956A32E1115D1EABC2E9F5 /* Debug */, + 17CDC4C0F8D77EC8C6301E0F603D7B15 /* Develop */, + 9F8B0E054D88C9FC8917BBFBC1360620 /* Release */, + D507D5924E1956DD46D4CEA4A90B6809 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DEA17664DA1352A9AF015846F7DC4098 /* Build configuration list for PBXNativeTarget "FirebaseCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 53551413403BE972D3E8493F09D2C8FD /* AppStore */, + 76B98C1F7279585A3DD4518B7A92A3F3 /* Debug */, + 68A8D49864B3832FE56A43ED9B1B123F /* Develop */, + 2E0BAC58EBC4FC3F5FD6C17B54A79FCE /* Release */, + 9965E55FC4DECB0117079BD67CF8878D /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DF9887486229B1728B84F6155310DF6E /* Build configuration list for PBXNativeTarget "AppCenter-AppCenterDistributeResources" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DA51A607CE00DD6264E22148850D773 /* AppStore */, + F13196A4950243EBC6D7E5A7CE023F74 /* Debug */, + FF90010BB3F5E1134B46DE5DA1CCB64E /* Develop */, + 3B2882C18947648D49623DE63CD7878B /* Release */, + 88BE0DFE71CC7168CFCC5C94FD68FBAF /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E242987B250CB1C0EA9B99A80377B33E /* Build configuration list for PBXNativeTarget "SimulatorStatusMagic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2E1070759DFCEAE5DBC3D05A79D21818 /* AppStore */, + 78C9F0FA9EF8EDD145018C7274250F50 /* Debug */, + 74F5C40245ED34AFFCCF455D62178E4D /* Develop */, + 1051691A092C7F9BF7A92E2499457D71 /* Release */, + 6B730C2AD0DC9F84451A95E0ED36711E /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E481993470B5B9DFECE3140821C2904E /* Build configuration list for PBXNativeTarget "nanopb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B842C542B2D62DF3B418AA5CF63FC75E /* AppStore */, + 00EB2E82A5B0B8A56724F99E9E52E4D1 /* Debug */, + 1CFF61CD09FAF75F0BC682385BFCFFF6 /* Develop */, + 92961265545DD48C54C580534E52CF68 /* Release */, + 9C70C99294CC907784B8B046DEE5ADD0 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EBAF0176DA76634D02397BD80DC087AD /* Build configuration list for PBXNativeTarget "BonMot" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C0B45A6DDB4DBDF13F8CE92C38F53C1 /* AppStore */, + 499E3B22BACADD3B8477C76F94E244B6 /* Debug */, + E4B02B37D44325E20D374DCD3C7C229B /* Develop */, + 85AD63334D8D13A60DFE0BB1071985A1 /* Release */, + 7F5387FAE75904C8004C212967CB3D9E /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EF7E77D70CE9CA6FA1C9D136EC7A4F62 /* Build configuration list for PBXAggregateTarget "AppCenter" */ = { isa = XCConfigurationList; buildConfigurations = ( - 204A727D957819558F27765EE2A2A1D6 /* AppStore */, - 4AFE1632DF385493AAF0959EAB15A6FB /* Debug */, - 474A0C0DEA0264E9C60832E18A81AEBD /* Develop */, - 124A4C27A8874D4DF4D59D2CA1F4CB37 /* Release */, - 3E5452AB2D04004B314626A29B4AAF3B /* Sprint */, + 04A2E9C489820651DDD7EBB81053B7F6 /* AppStore */, + 42E49BF53D9157BB9344A2CC526BACC5 /* Debug */, + 04A03498AB90701059293AFCA227A006 /* Develop */, + 0F25A9D4FB36C7AEE76E082640AEB849 /* Release */, + C0CC21FC535B013F47BA834C17EDE971 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - F97409124909E20C13076D42CA44F17F /* Build configuration list for PBXNativeTarget "BonMot" */ = { + F7527E454CF938C5B4E80CDBBF13A340 /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */ = { isa = XCConfigurationList; buildConfigurations = ( - 36DED9CF34365C7C4704E68F088A1C7A /* AppStore */, - 9EC75EA43BA76F31EEB1BB7A7457B93D /* Debug */, - 1AF58D3DF19E64ED279DA487BB8CFDFE /* Develop */, - EA54336624E67F8E2ACD8D9E659395B4 /* Release */, - B0FED054A7E207C28B6A0B875DF71DDE /* Sprint */, + 39AF457727CE54F1468C1931870EE8D7 /* AppStore */, + 0254BAE7CE7FF9132CED803AB907108A /* Debug */, + 6359B27DDFBAAE66820844B7D3BF1FA5 /* Develop */, + 88F1D88DE44D2B31391FB31F87F5420B /* Release */, + B44E2B38C771C5A2C004CA70C1C2B036 /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - F9ECB5FE2D8DF5EE0FCF85C2952CBD21 /* Build configuration list for PBXNativeTarget "Pods-Services" */ = { + F8BFF7D89DB99B737428DD3707FD5D7B /* Build configuration list for PBXNativeTarget "Pods-Services" */ = { isa = XCConfigurationList; buildConfigurations = ( - 65E229AD454727B1F65EAF577AD698CA /* AppStore */, - 42DE9E57338CCC305496EBDD26212F8A /* Debug */, - D3C43F12005E9F42072E5D6AFB71C529 /* Develop */, - 9EFD5255CC75346853858C253083DBB7 /* Release */, - 44F0B896D02B2BE4D3AB1DD26520E37B /* Sprint */, + D43D4960BF9B5B2EE70F2E74AC781C23 /* AppStore */, + EE9B60D8F1FED00BC5D55D35C2B67C86 /* Debug */, + 364397E9C482719315F8047008C221D2 /* Develop */, + DAAA5A6195EA66DEF295EFDB8229C517 /* Release */, + 1199DB3A26F46619A4FCEC8A16240B6F /* Sprint */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/PRODUCTNAME/app/Pods/Protobuf/LICENSE b/PRODUCTNAME/app/Pods/Protobuf/LICENSE new file mode 100644 index 0000000..19b305b --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/LICENSE @@ -0,0 +1,32 @@ +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. diff --git a/PRODUCTNAME/app/Pods/Protobuf/README.md b/PRODUCTNAME/app/Pods/Protobuf/README.md new file mode 100644 index 0000000..f622956 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/README.md @@ -0,0 +1,85 @@ +Protocol Buffers - Google's data interchange format +=================================================== + +Copyright 2008 Google Inc. + +https://developers.google.com/protocol-buffers/ + +Overview +-------- + +Protocol Buffers (a.k.a., protobuf) are Google's language-neutral, +platform-neutral, extensible mechanism for serializing structured data. You +can find [protobuf's documentation on the Google Developers site](https://developers.google.com/protocol-buffers/). + +This README file contains protobuf installation instructions. To install +protobuf, you need to install the protocol compiler (used to compile .proto +files) and the protobuf runtime for your chosen programming language. + +Protocol Compiler Installation +------------------------------ + +The protocol compiler is written in C++. If you are using C++, please follow +the [C++ Installation Instructions](src/README.md) to install protoc along +with the C++ runtime. + +For non-C++ users, the simplest way to install the protocol compiler is to +download a pre-built binary from our release page: + + [https://github.com/protocolbuffers/protobuf/releases](https://github.com/protocolbuffers/protobuf/releases) + +In the downloads section of each release, you can find pre-built binaries in +zip packages: protoc-$VERSION-$PLATFORM.zip. It contains the protoc binary +as well as a set of standard .proto files distributed along with protobuf. + +If you are looking for an old version that is not available in the release +page, check out the maven repo here: + + [https://repo1.maven.org/maven2/com/google/protobuf/protoc/](https://repo1.maven.org/maven2/com/google/protobuf/protoc/) + +These pre-built binaries are only provided for released versions. If you want +to use the github master version at HEAD, or you need to modify protobuf code, +or you are using C++, it's recommended to build your own protoc binary from +source. + +If you would like to build protoc binary from source, see the [C++ Installation +Instructions](src/README.md). + +Protobuf Runtime Installation +----------------------------- + +Protobuf supports several different programming languages. For each programming +language, you can find instructions in the corresponding source directory about +how to install protobuf runtime for that specific language: + +| Language | Source | Ubuntu | MacOS | Windows | +|--------------------------------------|-------------------------------------------------------------|--------|-------|---------| +| C++ (include C++ runtime and protoc) | [src](src) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) | +| Java | [java](java) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_jdk7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_jdk7%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_oracle7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_oracle7%2Fcontinuous) | | | +| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous) | | +| Objective-C | [objectivec](objectivec) | | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) | | +| C# | [csharp](csharp) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) | +| JavaScript | [js](js) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | | +| Ruby | [ruby](ruby) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby25%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby25%2Fcontinuous) | | +| Go | [golang/protobuf](https://github.com/golang/protobuf) | | | | +| PHP | [php](php) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-php_all.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fphp_all%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-32-bit.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2F32-bit%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php5.6_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp5.6_mac%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php7.0_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp7.0_mac%2Fcontinuous) | | +| Dart | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) | [![Build Status](https://travis-ci.org/dart-lang/protobuf.svg?branch=master)](https://travis-ci.org/dart-lang/protobuf) | | | + +Quick Start +----------- + +The best way to learn how to use protobuf is to follow the tutorials in our +developer guide: + +https://developers.google.com/protocol-buffers/docs/tutorials + +If you want to learn from code examples, take a look at the examples in the +[examples](examples) directory. + +Documentation +------------- + +The complete documentation for Protocol Buffers is available via the +web at: + +https://developers.google.com/protocol-buffers/ diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray.h new file mode 100644 index 0000000..3d22cb8 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray.h @@ -0,0 +1,1967 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +//%PDDM-EXPAND DECLARE_ARRAYS() +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 + +/** + * Class used for repeated fields of int32_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBInt32Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBInt32Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBInt32Array with value in it. + **/ ++ (instancetype)arrayWithValue:(int32_t)value; + +/** + * Creates and initializes a GPBInt32Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBInt32Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array; + +/** + * Creates and initializes a GPBInt32Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBInt32Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBInt32Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBInt32Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const int32_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBInt32Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBInt32Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBInt32Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (int32_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(int32_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const int32_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBInt32Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - UInt32 + +/** + * Class used for repeated fields of uint32_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBUInt32Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBUInt32Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBUInt32Array with value in it. + **/ ++ (instancetype)arrayWithValue:(uint32_t)value; + +/** + * Creates and initializes a GPBUInt32Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBUInt32Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array; + +/** + * Creates and initializes a GPBUInt32Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBUInt32Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBUInt32Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBUInt32Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const uint32_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBUInt32Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBUInt32Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBUInt32Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (uint32_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(uint32_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const uint32_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBUInt32Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Int64 + +/** + * Class used for repeated fields of int64_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBInt64Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBInt64Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBInt64Array with value in it. + **/ ++ (instancetype)arrayWithValue:(int64_t)value; + +/** + * Creates and initializes a GPBInt64Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBInt64Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array; + +/** + * Creates and initializes a GPBInt64Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBInt64Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBInt64Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBInt64Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const int64_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBInt64Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBInt64Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBInt64Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (int64_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(int64_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const int64_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBInt64Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - UInt64 + +/** + * Class used for repeated fields of uint64_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBUInt64Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBUInt64Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBUInt64Array with value in it. + **/ ++ (instancetype)arrayWithValue:(uint64_t)value; + +/** + * Creates and initializes a GPBUInt64Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBUInt64Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array; + +/** + * Creates and initializes a GPBUInt64Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBUInt64Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBUInt64Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBUInt64Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const uint64_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBUInt64Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBUInt64Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBUInt64Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (uint64_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(uint64_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const uint64_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBUInt64Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Float + +/** + * Class used for repeated fields of float values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBFloatArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBFloatArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBFloatArray with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBFloatArray with value in it. + **/ ++ (instancetype)arrayWithValue:(float)value; + +/** + * Creates and initializes a GPBFloatArray with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBFloatArray with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array; + +/** + * Creates and initializes a GPBFloatArray with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBFloatArray with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBFloatArray. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBFloatArray with a copy of the values. + **/ +- (instancetype)initWithValues:(const float [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBFloatArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBFloatArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBFloatArray with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (float)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(float)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const float [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBFloatArray *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(float)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Double + +/** + * Class used for repeated fields of double values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBDoubleArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBDoubleArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBDoubleArray with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBDoubleArray with value in it. + **/ ++ (instancetype)arrayWithValue:(double)value; + +/** + * Creates and initializes a GPBDoubleArray with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBDoubleArray with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array; + +/** + * Creates and initializes a GPBDoubleArray with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBDoubleArray with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBDoubleArray. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBDoubleArray with a copy of the values. + **/ +- (instancetype)initWithValues:(const double [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBDoubleArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBDoubleArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBDoubleArray with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (double)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(double)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const double [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBDoubleArray *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(double)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Bool + +/** + * Class used for repeated fields of BOOL values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBBoolArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBBoolArray with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBBoolArray with value in it. + **/ ++ (instancetype)arrayWithValue:(BOOL)value; + +/** + * Creates and initializes a GPBBoolArray with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBBoolArray with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array; + +/** + * Creates and initializes a GPBBoolArray with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBBoolArray with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBBoolArray. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBBoolArray with a copy of the values. + **/ +- (instancetype)initWithValues:(const BOOL [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBBoolArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBBoolArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBBoolArray with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (BOOL)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(BOOL)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const BOOL [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBBoolArray *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Enum + +/** + * This class is used for repeated fields of int32_t values. This performs + * better than boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBEnumArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * @return A newly instanced and empty GPBEnumArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBEnumArray with the enum validation function + * given. + * + * @param func The enum validation function for the array. + * + * @return A newly instanced GPBEnumArray. + **/ ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Creates and initializes a GPBEnumArray with the enum validation function + * given and the single raw value given. + * + * @param func The enum validation function for the array. + * @param value The raw value to add to this array. + * + * @return A newly instanced GPBEnumArray. + **/ ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValue:(int32_t)value; + +/** + * Creates and initializes a GPBEnumArray that adds the elements from the + * given array. + * + * @param array Array containing the values to add to the new array. + * + * @return A newly instanced GPBEnumArray. + **/ ++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array; + +/** + * Creates and initializes a GPBEnumArray with the given enum validation + * function and with the givencapacity. + * + * @param func The enum validation function for the array. + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBEnumArray with a capacity of count. + **/ ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)count; + +/** + * Initializes the array with the given enum validation function. + * + * @param func The enum validation function for the array. + * + * @return A newly initialized GPBEnumArray with a copy of the values. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param func The enum validation function for the array. + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBEnumArray with a copy of the values. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBEnumArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBEnumArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param func The enum validation function for the array. + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBEnumArray with a capacity of count. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)count; + +// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a +// valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (int32_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +// These methods bypass the validationFunc to provide access to values that were not +// known at the time the binary was compiled. + +/** + * Gets the raw enum value at the given index. + * + * @param index The index of the raw enum value to get. + * + * @return The raw enum value at the given index. + **/ +- (int32_t)rawValueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(int32_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const int32_t [__nullable])values count:(NSUInteger)count; + + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value; + +// These methods bypass the validationFunc to provide setting of values that were not +// known at the time the binary was compiled. + +/** + * Adds a raw enum value to this array. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param value The raw enum value to add to the array. + **/ +- (void)addRawValue:(int32_t)value; + +/** + * Adds raw enum values to this array. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param array Array containing the raw enum values to add to this array. + **/ +- (void)addRawValuesFromArray:(GPBEnumArray *)array; + +/** + * Adds raw enum values to this array. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param values Array containing the raw enum values to add to this array. + * @param count The number of raw values to add. + **/ +- (void)addRawValues:(const int32_t [__nullable])values count:(NSUInteger)count; + +/** + * Inserts a raw enum value at the given index. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param value Raw enum value to add. + * @param index The index into which to insert the value. + **/ +- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the raw enum value at the given index with the given value. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param index The index for which to replace the value. + * @param value The raw enum value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value; + +// No validation applies to these methods. + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +//%PDDM-EXPAND-END DECLARE_ARRAYS() + +NS_ASSUME_NONNULL_END + +//%PDDM-DEFINE DECLARE_ARRAYS() +//%ARRAY_INTERFACE_SIMPLE(Int32, int32_t) +//%ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t) +//%ARRAY_INTERFACE_SIMPLE(Int64, int64_t) +//%ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t) +//%ARRAY_INTERFACE_SIMPLE(Float, float) +//%ARRAY_INTERFACE_SIMPLE(Double, double) +//%ARRAY_INTERFACE_SIMPLE(Bool, BOOL) +//%ARRAY_INTERFACE_ENUM(Enum, int32_t) + +// +// The common case (everything but Enum) +// + +//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE) +//%#pragma mark - NAME +//% +//%/** +//% * Class used for repeated fields of ##TYPE## values. This performs better than +//% * boxing into NSNumbers in NSArrays. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface GPB##NAME##Array : NSObject +//% +//%/** The number of elements contained in the array. */ +//%@property(nonatomic, readonly) NSUInteger count; +//% +//%/** +//% * @return A newly instanced and empty GPB##NAME##Array. +//% **/ +//%+ (instancetype)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the single element given. +//% * +//% * @param value The value to be placed in the array. +//% * +//% * @return A newly instanced GPB##NAME##Array with value in it. +//% **/ +//%+ (instancetype)arrayWithValue:(TYPE)value; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the contents of the given +//% * array. +//% * +//% * @param array Array with the contents to be put into the new array. +//% * +//% * @return A newly instanced GPB##NAME##Array with the contents of array. +//% **/ +//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the given capacity. +//% * +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly instanced GPB##NAME##Array with a capacity of count. +//% **/ +//%+ (instancetype)arrayWithCapacity:(NSUInteger)count; +//% +//%/** +//% * @return A newly initialized and empty GPB##NAME##Array. +//% **/ +//%- (instancetype)init NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param values An array with the values to put inside this array. +//% * @param count The number of elements to copy into the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValues:(const TYPE [__nullable])values +//% count:(NSUInteger)count; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param array An array with the values to put inside this array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Initializes the array with the given capacity. +//% * +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a capacity of count. +//% **/ +//%- (instancetype)initWithCapacity:(NSUInteger)count; +//% +//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, Basic) +//% +//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, Basic) +//% +//%@end +//% + +// +// Macros specific to Enums (to tweak their interface). +// + +//%PDDM-DEFINE ARRAY_INTERFACE_ENUM(NAME, TYPE) +//%#pragma mark - NAME +//% +//%/** +//% * This class is used for repeated fields of ##TYPE## values. This performs +//% * better than boxing into NSNumbers in NSArrays. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface GPB##NAME##Array : NSObject +//% +//%/** The number of elements contained in the array. */ +//%@property(nonatomic, readonly) NSUInteger count; +//%/** The validation function to check if the enums are valid. */ +//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; +//% +//%/** +//% * @return A newly instanced and empty GPB##NAME##Array. +//% **/ +//%+ (instancetype)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the enum validation function +//% * given. +//% * +//% * @param func The enum validation function for the array. +//% * +//% * @return A newly instanced GPB##NAME##Array. +//% **/ +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the enum validation function +//% * given and the single raw value given. +//% * +//% * @param func The enum validation function for the array. +//% * @param value The raw value to add to this array. +//% * +//% * @return A newly instanced GPB##NAME##Array. +//% **/ +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% rawValue:(TYPE)value; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array that adds the elements from the +//% * given array. +//% * +//% * @param array Array containing the values to add to the new array. +//% * +//% * @return A newly instanced GPB##NAME##Array. +//% **/ +//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the given enum validation +//% * function and with the givencapacity. +//% * +//% * @param func The enum validation function for the array. +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly instanced GPB##NAME##Array with a capacity of count. +//% **/ +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% capacity:(NSUInteger)count; +//% +//%/** +//% * Initializes the array with the given enum validation function. +//% * +//% * @param func The enum validation function for the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param func The enum validation function for the array. +//% * @param values An array with the values to put inside this array. +//% * @param count The number of elements to copy into the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% rawValues:(const TYPE [__nullable])values +//% count:(NSUInteger)count; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param array An array with the values to put inside this array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Initializes the array with the given capacity. +//% * +//% * @param func The enum validation function for the array. +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a capacity of count. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% capacity:(NSUInteger)count; +//% +//%// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a +//%// valid enumerator as defined by validationFunc. If the actual value is +//%// desired, use "raw" version of the method. +//% +//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, NAME) +//% +//%// These methods bypass the validationFunc to provide access to values that were not +//%// known at the time the binary was compiled. +//% +//%/** +//% * Gets the raw enum value at the given index. +//% * +//% * @param index The index of the raw enum value to get. +//% * +//% * @return The raw enum value at the given index. +//% **/ +//%- (TYPE)rawValueAtIndex:(NSUInteger)index; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param opts Options to control the enumeration. +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts +//% usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% +//%// If value is not a valid enumerator as defined by validationFunc, these +//%// methods will assert in debug, and will log in release and assign the value +//%// to the default value. Use the rawValue methods below to assign non enumerator +//%// values. +//% +//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, NAME) +//% +//%@end +//% + +//%PDDM-DEFINE ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME) +//%/** +//% * Gets the value at the given index. +//% * +//% * @param index The index of the value to get. +//% * +//% * @return The value at the given index. +//% **/ +//%- (TYPE)valueAtIndex:(NSUInteger)index; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param opts Options to control the enumeration. +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts +//% usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; + +//%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME) +//%/** +//% * Adds a value to this array. +//% * +//% * @param value The value to add to this array. +//% **/ +//%- (void)addValue:(TYPE)value; +//% +//%/** +//% * Adds values to this array. +//% * +//% * @param values The values to add to this array. +//% * @param count The number of elements to add. +//% **/ +//%- (void)addValues:(const TYPE [__nullable])values count:(NSUInteger)count; +//% +//%ARRAY_EXTRA_MUTABLE_METHODS1_##HELPER_NAME(NAME, TYPE) +//%/** +//% * Inserts a value into the given position. +//% * +//% * @param value The value to add to this array. +//% * @param index The index into which to insert the value. +//% **/ +//%- (void)insertValue:(TYPE)value atIndex:(NSUInteger)index; +//% +//%/** +//% * Replaces the value at the given index with the given value. +//% * +//% * @param index The index for which to replace the value. +//% * @param value The value to replace with. +//% **/ +//%- (void)replaceValueAtIndex:(NSUInteger)index withValue:(TYPE)value; +//%ARRAY_EXTRA_MUTABLE_METHODS2_##HELPER_NAME(NAME, TYPE) +//%/** +//% * Removes the value at the given index. +//% * +//% * @param index The index of the value to remove. +//% **/ +//%- (void)removeValueAtIndex:(NSUInteger)index; +//% +//%/** +//% * Removes all the values from this array. +//% **/ +//%- (void)removeAll; +//% +//%/** +//% * Exchanges the values between the given indexes. +//% * +//% * @param idx1 The index of the first element to exchange. +//% * @param idx2 The index of the second element to exchange. +//% **/ +//%- (void)exchangeValueAtIndex:(NSUInteger)idx1 +//% withValueAtIndex:(NSUInteger)idx2; + +// +// These are hooks invoked by the above to do insert as needed. +// + +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Basic(NAME, TYPE) +//%/** +//% * Adds the values from the given array to this array. +//% * +//% * @param array The array containing the elements to add to this array. +//% **/ +//%- (void)addValuesFromArray:(GPB##NAME##Array *)array; +//% +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Basic(NAME, TYPE) +// Empty +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Enum(NAME, TYPE) +// Empty +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Enum(NAME, TYPE) +//% +//%// These methods bypass the validationFunc to provide setting of values that were not +//%// known at the time the binary was compiled. +//% +//%/** +//% * Adds a raw enum value to this array. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param value The raw enum value to add to the array. +//% **/ +//%- (void)addRawValue:(TYPE)value; +//% +//%/** +//% * Adds raw enum values to this array. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param array Array containing the raw enum values to add to this array. +//% **/ +//%- (void)addRawValuesFromArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Adds raw enum values to this array. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param values Array containing the raw enum values to add to this array. +//% * @param count The number of raw values to add. +//% **/ +//%- (void)addRawValues:(const TYPE [__nullable])values count:(NSUInteger)count; +//% +//%/** +//% * Inserts a raw enum value at the given index. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param value Raw enum value to add. +//% * @param index The index into which to insert the value. +//% **/ +//%- (void)insertRawValue:(TYPE)value atIndex:(NSUInteger)index; +//% +//%/** +//% * Replaces the raw enum value at the given index with the given value. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param index The index for which to replace the value. +//% * @param value The raw enum value to replace with. +//% **/ +//%- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(TYPE)value; +//% +//%// No validation applies to these methods. +//% diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray.m new file mode 100644 index 0000000..5ce1e59 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray.m @@ -0,0 +1,2551 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBArray_PackagePrivate.h" + +#import "GPBMessage_PackagePrivate.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +// Mutable arrays use an internal buffer that can always hold a multiple of this elements. +#define kChunkSize 16 +#define CapacityFromCount(x) (((x / kChunkSize) + 1) * kChunkSize) + +static BOOL ArrayDefault_IsValidValue(int32_t value) { + // Anything but the bad value marker is allowed. + return (value != kGPBUnrecognizedEnumeratorValue); +} + +//%PDDM-DEFINE VALIDATE_RANGE(INDEX, COUNT) +//% if (INDEX >= COUNT) { +//% [NSException raise:NSRangeException +//% format:@"Index (%lu) beyond bounds (%lu)", +//% (unsigned long)INDEX, (unsigned long)COUNT]; +//% } +//%PDDM-DEFINE MAYBE_GROW_TO_SET_COUNT(NEW_COUNT) +//% if (NEW_COUNT > _capacity) { +//% [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)]; +//% } +//% _count = NEW_COUNT; +//%PDDM-DEFINE SET_COUNT_AND_MAYBE_SHRINK(NEW_COUNT) +//% _count = NEW_COUNT; +//% if ((NEW_COUNT + (2 * kChunkSize)) < _capacity) { +//% [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)]; +//% } + +// +// Macros for the common basic cases. +// + +//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE, FORMAT) +//%#pragma mark - NAME +//% +//%@implementation GPB##NAME##Array { +//% @package +//% TYPE *_values; +//% NSUInteger _count; +//% NSUInteger _capacity; +//%} +//% +//%@synthesize count = _count; +//% +//%+ (instancetype)array { +//% return [[[self alloc] init] autorelease]; +//%} +//% +//%+ (instancetype)arrayWithValue:(TYPE)value { +//% // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get +//% // the type correct. +//% return [[(GPB##NAME##Array*)[self alloc] initWithValues:&value count:1] autorelease]; +//%} +//% +//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array { +//% return [[(GPB##NAME##Array*)[self alloc] initWithValueArray:array] autorelease]; +//%} +//% +//%+ (instancetype)arrayWithCapacity:(NSUInteger)count { +//% return [[[self alloc] initWithCapacity:count] autorelease]; +//%} +//% +//%- (instancetype)init { +//% self = [super init]; +//% // No work needed; +//% return self; +//%} +//% +//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array { +//% return [self initWithValues:array->_values count:array->_count]; +//%} +//% +//%- (instancetype)initWithValues:(const TYPE [])values count:(NSUInteger)count { +//% self = [self init]; +//% if (self) { +//% if (count && values) { +//% _values = reallocf(_values, count * sizeof(TYPE)); +//% if (_values != NULL) { +//% _capacity = count; +//% memcpy(_values, values, count * sizeof(TYPE)); +//% _count = count; +//% } else { +//% [self release]; +//% [NSException raise:NSMallocException +//% format:@"Failed to allocate %lu bytes", +//% (unsigned long)(count * sizeof(TYPE))]; +//% } +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithCapacity:(NSUInteger)count { +//% self = [self initWithValues:NULL count:0]; +//% if (self && count) { +//% [self internalResizeToCapacity:count]; +//% } +//% return self; +//%} +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { +//% return [[GPB##NAME##Array allocWithZone:zone] initWithValues:_values count:_count]; +//%} +//% +//%ARRAY_IMMUTABLE_CORE(NAME, TYPE, , FORMAT) +//% +//%- (TYPE)valueAtIndex:(NSUInteger)index { +//%VALIDATE_RANGE(index, _count) +//% return _values[index]; +//%} +//% +//%ARRAY_MUTABLE_CORE(NAME, TYPE, , FORMAT) +//%@end +//% + +// +// Some core macros used for both the simple types and Enums. +// + +//%PDDM-DEFINE ARRAY_IMMUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% free(_values); +//% [super dealloc]; +//%} +//% +//%- (BOOL)isEqual:(id)other { +//% if (self == other) { +//% return YES; +//% } +//% if (![other isKindOfClass:[GPB##NAME##Array class]]) { +//% return NO; +//% } +//% GPB##NAME##Array *otherArray = other; +//% return (_count == otherArray->_count +//% && memcmp(_values, otherArray->_values, (_count * sizeof(TYPE))) == 0); +//%} +//% +//%- (NSUInteger)hash { +//% // Follow NSArray's lead, and use the count as the hash. +//% return _count; +//%} +//% +//%- (NSString *)description { +//% NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; +//% for (NSUInteger i = 0, count = _count; i < count; ++i) { +//% if (i == 0) { +//% [result appendFormat:@"##FORMAT##", _values[i]]; +//% } else { +//% [result appendFormat:@", ##FORMAT##", _values[i]]; +//% } +//% } +//% [result appendFormat:@" }"]; +//% return result; +//%} +//% +//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block { +//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +//%} +//% +//%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts +//% ACCESSOR_NAME$S usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block { +//% // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). +//% BOOL stop = NO; +//% if ((opts & NSEnumerationReverse) == 0) { +//% for (NSUInteger i = 0, count = _count; i < count; ++i) { +//% block(_values[i], i, &stop); +//% if (stop) break; +//% } +//% } else if (_count > 0) { +//% for (NSUInteger i = _count; i > 0; --i) { +//% block(_values[i - 1], (i - 1), &stop); +//% if (stop) break; +//% } +//% } +//%} + +//%PDDM-DEFINE MUTATION_HOOK_None() +//%PDDM-DEFINE MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, HOOK_1, HOOK_2) +//%- (void)add##ACCESSOR_NAME##Value:(TYPE)value { +//% [self add##ACCESSOR_NAME##Values:&value count:1]; +//%} +//% +//%- (void)add##ACCESSOR_NAME##Values:(const TYPE [])values count:(NSUInteger)count { +//% if (values == NULL || count == 0) return; +//%MUTATION_HOOK_##HOOK_1() NSUInteger initialCount = _count; +//% NSUInteger newCount = initialCount + count; +//%MAYBE_GROW_TO_SET_COUNT(newCount) +//% memcpy(&_values[initialCount], values, count * sizeof(TYPE)); +//% if (_autocreator) { +//% GPBAutocreatedArrayModified(_autocreator, self); +//% } +//%} +//% +//%- (void)insert##ACCESSOR_NAME##Value:(TYPE)value atIndex:(NSUInteger)index { +//%VALIDATE_RANGE(index, _count + 1) +//%MUTATION_HOOK_##HOOK_2() NSUInteger initialCount = _count; +//% NSUInteger newCount = initialCount + 1; +//%MAYBE_GROW_TO_SET_COUNT(newCount) +//% if (index != initialCount) { +//% memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(TYPE)); +//% } +//% _values[index] = value; +//% if (_autocreator) { +//% GPBAutocreatedArrayModified(_autocreator, self); +//% } +//%} +//% +//%- (void)replaceValueAtIndex:(NSUInteger)index with##ACCESSOR_NAME##Value:(TYPE)value { +//%VALIDATE_RANGE(index, _count) +//%MUTATION_HOOK_##HOOK_2() _values[index] = value; +//%} + +//%PDDM-DEFINE ARRAY_MUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT) +//%- (void)internalResizeToCapacity:(NSUInteger)newCapacity { +//% _values = reallocf(_values, newCapacity * sizeof(TYPE)); +//% if (_values == NULL) { +//% _capacity = 0; +//% _count = 0; +//% [NSException raise:NSMallocException +//% format:@"Failed to allocate %lu bytes", +//% (unsigned long)(newCapacity * sizeof(TYPE))]; +//% } +//% _capacity = newCapacity; +//%} +//% +//%MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, None, None) +//% +//%- (void)add##ACCESSOR_NAME##ValuesFromArray:(GPB##NAME##Array *)array { +//% [self add##ACCESSOR_NAME##Values:array->_values count:array->_count]; +//%} +//% +//%- (void)removeValueAtIndex:(NSUInteger)index { +//%VALIDATE_RANGE(index, _count) +//% NSUInteger newCount = _count - 1; +//% if (index != newCount) { +//% memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(TYPE)); +//% } +//%SET_COUNT_AND_MAYBE_SHRINK(newCount) +//%} +//% +//%- (void)removeAll { +//%SET_COUNT_AND_MAYBE_SHRINK(0) +//%} +//% +//%- (void)exchangeValueAtIndex:(NSUInteger)idx1 +//% withValueAtIndex:(NSUInteger)idx2 { +//%VALIDATE_RANGE(idx1, _count) +//%VALIDATE_RANGE(idx2, _count) +//% TYPE temp = _values[idx1]; +//% _values[idx1] = _values[idx2]; +//% _values[idx2] = temp; +//%} +//% + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int32, int32_t, %d) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 + +@implementation GPBInt32Array { + @package + int32_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(int32_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBInt32Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array { + return [[(GPBInt32Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBInt32Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const int32_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(int32_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(int32_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(int32_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32Array class]]) { + return NO; + } + GPBInt32Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(int32_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%d", _values[i]]; + } else { + [result appendFormat:@", %d", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (int32_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(int32_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(int32_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(int32_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const int32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBInt32Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + int32_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t, %u) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt32 + +@implementation GPBUInt32Array { + @package + uint32_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(uint32_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBUInt32Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array { + return [[(GPBUInt32Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBUInt32Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const uint32_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(uint32_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(uint32_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(uint32_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32Array class]]) { + return NO; + } + GPBUInt32Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(uint32_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%u", _values[i]]; + } else { + [result appendFormat:@", %u", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (uint32_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(uint32_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(uint32_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(uint32_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const uint32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(uint32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBUInt32Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint32_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + uint32_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int64, int64_t, %lld) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int64 + +@implementation GPBInt64Array { + @package + int64_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(int64_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBInt64Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array { + return [[(GPBInt64Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBInt64Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const int64_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(int64_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(int64_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(int64_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64Array class]]) { + return NO; + } + GPBInt64Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(int64_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%lld", _values[i]]; + } else { + [result appendFormat:@", %lld", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (int64_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(int64_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(int64_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(int64_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const int64_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int64_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int64_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBInt64Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int64_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + int64_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t, %llu) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt64 + +@implementation GPBUInt64Array { + @package + uint64_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(uint64_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBUInt64Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array { + return [[(GPBUInt64Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBUInt64Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const uint64_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(uint64_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(uint64_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(uint64_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64Array class]]) { + return NO; + } + GPBUInt64Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(uint64_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%llu", _values[i]]; + } else { + [result appendFormat:@", %llu", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (uint64_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(uint64_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(uint64_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(uint64_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const uint64_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(uint64_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint64_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBUInt64Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint64_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + uint64_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Float, float, %f) +// This block of code is generated, do not edit it directly. + +#pragma mark - Float + +@implementation GPBFloatArray { + @package + float *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(float)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBFloatArray*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array { + return [[(GPBFloatArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBFloatArray *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const float [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(float)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(float)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(float))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBFloatArray allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBFloatArray class]]) { + return NO; + } + GPBFloatArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(float))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%f", _values[i]]; + } else { + [result appendFormat:@", %f", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (float)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(float)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(float))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(float)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const float [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(float)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(float)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(float)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBFloatArray *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(float)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + float temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Double, double, %lf) +// This block of code is generated, do not edit it directly. + +#pragma mark - Double + +@implementation GPBDoubleArray { + @package + double *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(double)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBDoubleArray*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array { + return [[(GPBDoubleArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBDoubleArray *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const double [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(double)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(double)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(double))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBDoubleArray allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBDoubleArray class]]) { + return NO; + } + GPBDoubleArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(double))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%lf", _values[i]]; + } else { + [result appendFormat:@", %lf", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (double)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(double)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(double))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(double)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const double [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(double)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(double)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(double)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBDoubleArray *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(double)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + double temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Bool, BOOL, %d) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool + +@implementation GPBBoolArray { + @package + BOOL *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(BOOL)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBBoolArray*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array { + return [[(GPBBoolArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBBoolArray *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const BOOL [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(BOOL)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(BOOL)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(BOOL))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolArray allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolArray class]]) { + return NO; + } + GPBBoolArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(BOOL))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%d", _values[i]]; + } else { + [result appendFormat:@", %d", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (BOOL)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(BOOL)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(BOOL))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(BOOL)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const BOOL [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(BOOL)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(BOOL)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBBoolArray *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(BOOL)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + BOOL temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND-END (7 expansions) + +#pragma mark - Enum + +@implementation GPBEnumArray { + @package + GPBEnumValidationFunc _validationFunc; + int32_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; +@synthesize validationFunc = _validationFunc; + ++ (instancetype)array { + return [[[self alloc] initWithValidationFunction:NULL] autorelease]; +} + ++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func { + return [[[self alloc] initWithValidationFunction:func] autorelease]; +} + ++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func + rawValue:(int32_t)value { + return [[[self alloc] initWithValidationFunction:func + rawValues:&value + count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array { + return [[(GPBEnumArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)count { + return [[[self alloc] initWithValidationFunction:func capacity:count] autorelease]; +} + +- (instancetype)init { + return [self initWithValidationFunction:NULL]; +} + +- (instancetype)initWithValueArray:(GPBEnumArray *)array { + return [self initWithValidationFunction:array->_validationFunc + rawValues:array->_values + count:array->_count]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + self = [super init]; + if (self) { + _validationFunc = (func != NULL ? func : ArrayDefault_IsValidValue); + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])values + count:(NSUInteger)count { + self = [self initWithValidationFunction:func]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(int32_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(int32_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(int32_t))]; + } + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)count { + self = [self initWithValidationFunction:func]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBEnumArray allocWithZone:zone] + initWithValidationFunction:_validationFunc + rawValues:_values + count:_count]; +} + +//%PDDM-EXPAND ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d) +// This block of code is generated, do not edit it directly. + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBEnumArray class]]) { + return NO; + } + GPBEnumArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(int32_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%d", _values[i]]; + } else { + [result appendFormat:@", %d", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateRawValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} +//%PDDM-EXPAND-END ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d) + +- (int32_t)valueAtIndex:(NSUInteger)index { +//%PDDM-EXPAND VALIDATE_RANGE(index, _count) +// This block of code is generated, do not edit it directly. + + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } +//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count) + int32_t result = _values[index]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + return result; +} + +- (int32_t)rawValueAtIndex:(NSUInteger)index { +//%PDDM-EXPAND VALIDATE_RANGE(index, _count) +// This block of code is generated, do not edit it directly. + + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } +//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count) + return _values[index]; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + GPBEnumValidationFunc func = _validationFunc; + if ((opts & NSEnumerationReverse) == 0) { + int32_t *scan = _values; + int32_t *end = scan + _count; + for (NSUInteger i = 0; scan < end; ++i, ++scan) { + int32_t value = *scan; + if (!func(value)) { + value = kGPBUnrecognizedEnumeratorValue; + } + block(value, i, &stop); + if (stop) break; + } + } else if (_count > 0) { + int32_t *end = _values; + int32_t *scan = end + (_count - 1); + for (NSUInteger i = (_count - 1); scan >= end; --i, --scan) { + int32_t value = *scan; + if (!func(value)) { + value = kGPBUnrecognizedEnumeratorValue; + } + block(value, i, &stop); + if (stop) break; + } + } +} + +//%PDDM-EXPAND ARRAY_MUTABLE_CORE(Enum, int32_t, Raw, %d) +// This block of code is generated, do not edit it directly. + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(int32_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(int32_t))]; + } + _capacity = newCapacity; +} + +- (void)addRawValue:(int32_t)value { + [self addRawValues:&value count:1]; +} + +- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addRawValuesFromArray:(GPBEnumArray *)array { + [self addRawValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + int32_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +//%PDDM-EXPAND MUTATION_METHODS(Enum, int32_t, , EnumValidationList, EnumValidationOne) +// This block of code is generated, do not edit it directly. + +- (void)addValue:(int32_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const int32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + GPBEnumValidationFunc func = _validationFunc; + for (NSUInteger i = 0; i < count; ++i) { + if (!func(values[i])) { + [NSException raise:NSInvalidArgumentException + format:@"%@: Attempt to set an unknown enum value (%d)", + [self class], values[i]]; + } + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"%@: Attempt to set an unknown enum value (%d)", + [self class], value]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"%@: Attempt to set an unknown enum value (%d)", + [self class], value]; + } + _values[index] = value; +} +//%PDDM-EXPAND-END (2 expansions) + +//%PDDM-DEFINE MUTATION_HOOK_EnumValidationList() +//% GPBEnumValidationFunc func = _validationFunc; +//% for (NSUInteger i = 0; i < count; ++i) { +//% if (!func(values[i])) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"%@: Attempt to set an unknown enum value (%d)", +//% [self class], values[i]]; +//% } +//% } +//% +//%PDDM-DEFINE MUTATION_HOOK_EnumValidationOne() +//% if (!_validationFunc(value)) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"%@: Attempt to set an unknown enum value (%d)", +//% [self class], value]; +//% } +//% + +@end + +#pragma mark - NSArray Subclass + +@implementation GPBAutocreatedArray { + NSMutableArray *_array; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_array release]; + [super dealloc]; +} + +#pragma mark Required NSArray overrides + +- (NSUInteger)count { + return [_array count]; +} + +- (id)objectAtIndex:(NSUInteger)idx { + return [_array objectAtIndex:idx]; +} + +#pragma mark Required NSMutableArray overrides + +// Only need to call GPBAutocreatedArrayModified() when adding things since +// we only autocreate empty arrays. + +- (void)insertObject:(id)anObject atIndex:(NSUInteger)idx { + if (_array == nil) { + _array = [[NSMutableArray alloc] init]; + } + [_array insertObject:anObject atIndex:idx]; + + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)removeObject:(id)anObject { + [_array removeObject:anObject]; +} + +- (void)removeObjectAtIndex:(NSUInteger)idx { + [_array removeObjectAtIndex:idx]; +} + +- (void)addObject:(id)anObject { + if (_array == nil) { + _array = [[NSMutableArray alloc] init]; + } + [_array addObject:anObject]; + + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)removeLastObject { + [_array removeLastObject]; +} + +- (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)anObject { + [_array replaceObjectAtIndex:idx withObject:anObject]; +} + +#pragma mark Extra things hooked + +- (id)copyWithZone:(NSZone *)zone { + if (_array == nil) { + return [[NSMutableArray allocWithZone:zone] init]; + } + return [_array copyWithZone:zone]; +} + +- (id)mutableCopyWithZone:(NSZone *)zone { + if (_array == nil) { + return [[NSMutableArray allocWithZone:zone] init]; + } + return [_array mutableCopyWithZone:zone]; +} + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(id __unsafe_unretained [])buffer + count:(NSUInteger)len { + return [_array countByEnumeratingWithState:state objects:buffer count:len]; +} + +- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block { + [_array enumerateObjectsUsingBlock:block]; +} + +- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block { + [_array enumerateObjectsWithOptions:opts usingBlock:block]; +} + +@end + +#pragma clang diagnostic pop diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray_PackagePrivate.h new file mode 100644 index 0000000..35a4538 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBArray_PackagePrivate.h @@ -0,0 +1,130 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBArray.h" + +@class GPBMessage; + +//%PDDM-DEFINE DECLARE_ARRAY_EXTRAS() +//%ARRAY_INTERFACE_EXTRAS(Int32, int32_t) +//%ARRAY_INTERFACE_EXTRAS(UInt32, uint32_t) +//%ARRAY_INTERFACE_EXTRAS(Int64, int64_t) +//%ARRAY_INTERFACE_EXTRAS(UInt64, uint64_t) +//%ARRAY_INTERFACE_EXTRAS(Float, float) +//%ARRAY_INTERFACE_EXTRAS(Double, double) +//%ARRAY_INTERFACE_EXTRAS(Bool, BOOL) +//%ARRAY_INTERFACE_EXTRAS(Enum, int32_t) + +//%PDDM-DEFINE ARRAY_INTERFACE_EXTRAS(NAME, TYPE) +//%#pragma mark - NAME +//% +//%@interface GPB##NAME##Array () { +//% @package +//% GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +//%} +//%@end +//% + +//%PDDM-EXPAND DECLARE_ARRAY_EXTRAS() +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 + +@interface GPBInt32Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - UInt32 + +@interface GPBUInt32Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Int64 + +@interface GPBInt64Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - UInt64 + +@interface GPBUInt64Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Float + +@interface GPBFloatArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Double + +@interface GPBDoubleArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Bool + +@interface GPBBoolArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Enum + +@interface GPBEnumArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +//%PDDM-EXPAND-END DECLARE_ARRAY_EXTRAS() + +#pragma mark - NSArray Subclass + +@interface GPBAutocreatedArray : NSMutableArray { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBBootstrap.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBBootstrap.h new file mode 100644 index 0000000..0ebca25 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBBootstrap.h @@ -0,0 +1,141 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** + * The Objective C runtime has complete enough info that most protos don’t end + * up using this, so leaving it on is no cost or very little cost. If you + * happen to see it causing bloat, this is the way to disable it. If you do + * need to disable it, try only disabling it for Release builds as having + * full TextFormat can be useful for debugging. + **/ +#ifndef GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS +#define GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS 0 +#endif + +// Used in the generated code to give sizes to enums. int32_t was chosen based +// on the fact that Protocol Buffers enums are limited to this range. +#if !__has_feature(objc_fixed_enum) + #error All supported Xcode versions should support objc_fixed_enum. +#endif + +// If the headers are imported into Objective-C++, we can run into an issue +// where the defintion of NS_ENUM (really CF_ENUM) changes based on the C++ +// standard that is in effect. If it isn't C++11 or higher, the definition +// doesn't allow us to forward declare. We work around this one case by +// providing a local definition. The default case has to use NS_ENUM for the +// magic that is Swift bridging of enums. +#if (defined(__cplusplus) && __cplusplus && __cplusplus < 201103L) + #define GPB_ENUM(X) enum X : int32_t X; enum X : int32_t +#else + #define GPB_ENUM(X) NS_ENUM(int32_t, X) +#endif + +/** + * GPB_ENUM_FWD_DECLARE is used for forward declaring enums, for example: + * + * ``` + * GPB_ENUM_FWD_DECLARE(Foo_Enum) + * + * @interface BarClass : NSObject + * @property (nonatomic) enum Foo_Enum value; + * - (void)bazMethod:(enum Foo_Enum):value; + * @end + * ``` + **/ +#define GPB_ENUM_FWD_DECLARE(X) enum X : int32_t + +/** + * Based upon CF_INLINE. Forces inlining in non DEBUG builds. + **/ +#if !defined(DEBUG) +#define GPB_INLINE static __inline__ __attribute__((always_inline)) +#else +#define GPB_INLINE static __inline__ +#endif + +/** + * For use in public headers that might need to deal with ARC. + **/ +#ifndef GPB_UNSAFE_UNRETAINED +#if __has_feature(objc_arc) +#define GPB_UNSAFE_UNRETAINED __unsafe_unretained +#else +#define GPB_UNSAFE_UNRETAINED +#endif +#endif + +/** + * Attribute used for Objective-C proto interface deprecations without messages. + **/ +#ifndef GPB_DEPRECATED +#define GPB_DEPRECATED __attribute__((deprecated)) +#endif + +/** + * Attribute used for Objective-C proto interface deprecations with messages. + **/ +#ifndef GPB_DEPRECATED_MSG +#if __has_extension(attribute_deprecated_with_message) +#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) +#else +#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated)) +#endif +#endif + +// If property name starts with init we need to annotate it to get past ARC. +// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 +// +// Meant to be used internally by generated code. +#define GPB_METHOD_FAMILY_NONE __attribute__((objc_method_family(none))) + +// ---------------------------------------------------------------------------- +// These version numbers are all internal to the ObjC Protobuf runtime; they +// are used to ensure compatibility between the generated sources and the +// headers being compiled against and/or the version of sources being run +// against. +// +// They are all #defines so the values are captured into every .o file they +// are used in and to allow comparisons in the preprocessor. + +// Current library runtime version. +// - Gets bumped when the runtime makes changes to the interfaces between the +// generated code and runtime (things added/removed, etc). +#define GOOGLE_PROTOBUF_OBJC_VERSION 30002 + +// Minimum runtime version supported for compiling/running against. +// - Gets changed when support for the older generated code is dropped. +#define GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION 30001 + + +// This is a legacy constant now frozen in time for old generated code. If +// GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION ever gets moved above 30001 then +// this should also change to break code compiled with an old runtime that +// can't be supported any more. +#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001 diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream.h new file mode 100644 index 0000000..fbe5009 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream.h @@ -0,0 +1,253 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBMessage; +@class GPBExtensionRegistry; + +NS_ASSUME_NONNULL_BEGIN + +CF_EXTERN_C_BEGIN + +/** + * @c GPBCodedInputStream exception name. Exceptions raised from + * @c GPBCodedInputStream contain an underlying error in the userInfo dictionary + * under the GPBCodedInputStreamUnderlyingErrorKey key. + **/ +extern NSString *const GPBCodedInputStreamException; + +/** The key under which the underlying NSError from the exception is stored. */ +extern NSString *const GPBCodedInputStreamUnderlyingErrorKey; + +/** NSError domain used for @c GPBCodedInputStream errors. */ +extern NSString *const GPBCodedInputStreamErrorDomain; + +/** + * Error code for NSError with @c GPBCodedInputStreamErrorDomain. + **/ +typedef NS_ENUM(NSInteger, GPBCodedInputStreamErrorCode) { + /** The size does not fit in the remaining bytes to be read. */ + GPBCodedInputStreamErrorInvalidSize = -100, + /** Attempted to read beyond the subsection limit. */ + GPBCodedInputStreamErrorSubsectionLimitReached = -101, + /** The requested subsection limit is invalid. */ + GPBCodedInputStreamErrorInvalidSubsectionLimit = -102, + /** Invalid tag read. */ + GPBCodedInputStreamErrorInvalidTag = -103, + /** Invalid UTF-8 character in a string. */ + GPBCodedInputStreamErrorInvalidUTF8 = -104, + /** Invalid VarInt read. */ + GPBCodedInputStreamErrorInvalidVarInt = -105, + /** The maximum recursion depth of messages was exceeded. */ + GPBCodedInputStreamErrorRecursionDepthExceeded = -106, +}; + +CF_EXTERN_C_END + +/** + * Reads and decodes protocol message fields. + * + * The common uses of protocol buffers shouldn't need to use this class. + * @c GPBMessage's provide a @c +parseFromData:error: and + * @c +parseFromData:extensionRegistry:error: method that will decode a + * message for you. + * + * @note Subclassing of @c GPBCodedInputStream is NOT supported. + **/ +@interface GPBCodedInputStream : NSObject + +/** + * Creates a new stream wrapping some data. + * + * @param data The data to wrap inside the stream. + * + * @return A newly instanced GPBCodedInputStream. + **/ ++ (instancetype)streamWithData:(NSData *)data; + +/** + * Initializes a stream wrapping some data. + * + * @param data The data to wrap inside the stream. + * + * @return A newly initialized GPBCodedInputStream. + **/ +- (instancetype)initWithData:(NSData *)data; + +/** + * Attempts to read a field tag, returning zero if we have reached EOF. + * Protocol message parsers use this to read tags, since a protocol message + * may legally end wherever a tag occurs, and zero is not a valid tag number. + * + * @return The field tag, or zero if EOF was reached. + **/ +- (int32_t)readTag; + +/** + * @return A double read from the stream. + **/ +- (double)readDouble; +/** + * @return A float read from the stream. + **/ +- (float)readFloat; +/** + * @return A uint64 read from the stream. + **/ +- (uint64_t)readUInt64; +/** + * @return A uint32 read from the stream. + **/ +- (uint32_t)readUInt32; +/** + * @return An int64 read from the stream. + **/ +- (int64_t)readInt64; +/** + * @return An int32 read from the stream. + **/ +- (int32_t)readInt32; +/** + * @return A fixed64 read from the stream. + **/ +- (uint64_t)readFixed64; +/** + * @return A fixed32 read from the stream. + **/ +- (uint32_t)readFixed32; +/** + * @return An enum read from the stream. + **/ +- (int32_t)readEnum; +/** + * @return A sfixed32 read from the stream. + **/ +- (int32_t)readSFixed32; +/** + * @return A fixed64 read from the stream. + **/ +- (int64_t)readSFixed64; +/** + * @return A sint32 read from the stream. + **/ +- (int32_t)readSInt32; +/** + * @return A sint64 read from the stream. + **/ +- (int64_t)readSInt64; +/** + * @return A boolean read from the stream. + **/ +- (BOOL)readBool; +/** + * @return A string read from the stream. + **/ +- (NSString *)readString; +/** + * @return Data read from the stream. + **/ +- (NSData *)readBytes; + +/** + * Read an embedded message field value from the stream. + * + * @param message The message to set fields on as they are read. + * @param extensionRegistry An optional extension registry to use to lookup + * extensions for message. + **/ +- (void)readMessage:(GPBMessage *)message + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry; + +/** + * Reads and discards a single field, given its tag value. + * + * @param tag The tag number of the field to skip. + * + * @return NO if the tag is an endgroup tag (in which case nothing is skipped), + * YES in all other cases. + **/ +- (BOOL)skipField:(int32_t)tag; + +/** + * Reads and discards an entire message. This will read either until EOF or + * until an endgroup tag, whichever comes first. + **/ +- (void)skipMessage; + +/** + * Check to see if the logical end of the stream has been reached. + * + * @note This can return NO when there is no more data, but the current parsing + * expected more data. + * + * @return YES if the logical end of the stream has been reached, NO otherwise. + **/ +- (BOOL)isAtEnd; + +/** + * @return The offset into the stream. + **/ +- (size_t)position; + +/** + * Moves the limit to the given byte offset starting at the current location. + * + * @exception GPBCodedInputStreamException If the requested bytes exceeed the + * current limit. + * + * @param byteLimit The number of bytes to move the limit, offset to the current + * location. + * + * @return The limit offset before moving the new limit. + */ +- (size_t)pushLimit:(size_t)byteLimit; + +/** + * Moves the limit back to the offset as it was before calling pushLimit:. + * + * @param oldLimit The number of bytes to move the current limit. Usually this + * is the value returned by the pushLimit: method. + */ +- (void)popLimit:(size_t)oldLimit; + +/** + * Verifies that the last call to -readTag returned the given tag value. This + * is used to verify that a nested group ended with the correct end tag. + * + * @exception NSParseErrorException If the value does not match the last tag. + * + * @param expected The tag that was expected. + **/ +- (void)checkLastTagWas:(int32_t)expected; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream.m new file mode 100644 index 0000000..57d04dd --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream.m @@ -0,0 +1,505 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBCodedInputStream_PackagePrivate.h" + +#import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" +#import "GPBWireFormat.h" + +NSString *const GPBCodedInputStreamException = + GPBNSStringifySymbol(GPBCodedInputStreamException); + +NSString *const GPBCodedInputStreamUnderlyingErrorKey = + GPBNSStringifySymbol(GPBCodedInputStreamUnderlyingErrorKey); + +NSString *const GPBCodedInputStreamErrorDomain = + GPBNSStringifySymbol(GPBCodedInputStreamErrorDomain); + +// Matching: +// https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L62 +// private static final int DEFAULT_RECURSION_LIMIT = 100; +// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/io/coded_stream.cc#L86 +// int CodedInputStream::default_recursion_limit_ = 100; +static const NSUInteger kDefaultRecursionLimit = 100; + +static void RaiseException(NSInteger code, NSString *reason) { + NSDictionary *errorInfo = nil; + if ([reason length]) { + errorInfo = @{ GPBErrorReasonKey: reason }; + } + NSError *error = [NSError errorWithDomain:GPBCodedInputStreamErrorDomain + code:code + userInfo:errorInfo]; + + NSDictionary *exceptionInfo = + @{ GPBCodedInputStreamUnderlyingErrorKey: error }; + [[NSException exceptionWithName:GPBCodedInputStreamException + reason:reason + userInfo:exceptionInfo] raise]; +} + +static void CheckRecursionLimit(GPBCodedInputStreamState *state) { + if (state->recursionDepth >= kDefaultRecursionLimit) { + RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); + } +} + +static void CheckSize(GPBCodedInputStreamState *state, size_t size) { + size_t newSize = state->bufferPos + size; + if (newSize > state->bufferSize) { + RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); + } + if (newSize > state->currentLimit) { + // Fast forward to end of currentLimit; + state->bufferPos = state->currentLimit; + RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil); + } +} + +static int8_t ReadRawByte(GPBCodedInputStreamState *state) { + CheckSize(state, sizeof(int8_t)); + return ((int8_t *)state->bytes)[state->bufferPos++]; +} + +static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { + CheckSize(state, sizeof(int32_t)); + int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos); + state->bufferPos += sizeof(int32_t); + return value; +} + +static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { + CheckSize(state, sizeof(int64_t)); + int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos); + state->bufferPos += sizeof(int64_t); + return value; +} + +static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { + int32_t shift = 0; + int64_t result = 0; + while (shift < 64) { + int8_t b = ReadRawByte(state); + result |= (int64_t)((uint64_t)(b & 0x7F) << shift); + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64"); + return 0; +} + +static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { + return (int32_t)ReadRawVarint64(state); +} + +static void SkipRawData(GPBCodedInputStreamState *state, size_t size) { + CheckSize(state, size); + state->bufferPos += size; +} + +double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state) { + int64_t value = ReadRawLittleEndian64(state); + return GPBConvertInt64ToDouble(value); +} + +float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state) { + int32_t value = ReadRawLittleEndian32(state); + return GPBConvertInt32ToFloat(value); +} + +uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state) { + uint64_t value = ReadRawVarint64(state); + return value; +} + +uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state) { + uint32_t value = ReadRawVarint32(state); + return value; +} + +int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state) { + int64_t value = ReadRawVarint64(state); + return value; +} + +int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state) { + int32_t value = ReadRawVarint32(state); + return value; +} + +uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state) { + uint64_t value = ReadRawLittleEndian64(state); + return value; +} + +uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state) { + uint32_t value = ReadRawLittleEndian32(state); + return value; +} + +int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state) { + int32_t value = ReadRawVarint32(state); + return value; +} + +int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state) { + int32_t value = ReadRawLittleEndian32(state); + return value; +} + +int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state) { + int64_t value = ReadRawLittleEndian64(state); + return value; +} + +int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state) { + int32_t value = GPBDecodeZigZag32(ReadRawVarint32(state)); + return value; +} + +int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) { + int64_t value = GPBDecodeZigZag64(ReadRawVarint64(state)); + return value; +} + +BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) { + return ReadRawVarint32(state) != 0; +} + +int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { + if (GPBCodedInputStreamIsAtEnd(state)) { + state->lastTag = 0; + return 0; + } + + state->lastTag = ReadRawVarint32(state); + // Tags have to include a valid wireformat. + if (!GPBWireFormatIsValidTag(state->lastTag)) { + RaiseException(GPBCodedInputStreamErrorInvalidTag, + @"Invalid wireformat in tag."); + } + // Zero is not a valid field number. + if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) { + RaiseException(GPBCodedInputStreamErrorInvalidTag, + @"A zero field number on the wire is invalid."); + } + return state->lastTag; +} + +NSString *GPBCodedInputStreamReadRetainedString( + GPBCodedInputStreamState *state) { + int32_t size = ReadRawVarint32(state); + NSString *result; + if (size == 0) { + result = @""; + } else { + CheckSize(state, size); + result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos] + length:size + encoding:NSUTF8StringEncoding]; + state->bufferPos += size; + if (!result) { +#ifdef DEBUG + // https://developers.google.com/protocol-buffers/docs/proto#scalar + NSLog(@"UTF-8 failure, is some field type 'string' when it should be " + @"'bytes'?"); +#endif + RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil); + } + } + return result; +} + +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) { + int32_t size = ReadRawVarint32(state); + if (size < 0) return nil; + CheckSize(state, size); + NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos + length:size]; + state->bufferPos += size; + return result; +} + +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( + GPBCodedInputStreamState *state) { + int32_t size = ReadRawVarint32(state); + if (size < 0) return nil; + CheckSize(state, size); + // Cast is safe because freeWhenDone is NO. + NSData *result = [[NSData alloc] + initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos) + length:size + freeWhenDone:NO]; + state->bufferPos += size; + return result; +} + +size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, + size_t byteLimit) { + byteLimit += state->bufferPos; + size_t oldLimit = state->currentLimit; + if (byteLimit > oldLimit) { + RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil); + } + state->currentLimit = byteLimit; + return oldLimit; +} + +void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, + size_t oldLimit) { + state->currentLimit = oldLimit; +} + +size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state) { + return state->currentLimit - state->bufferPos; +} + +BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) { + return (state->bufferPos == state->bufferSize) || + (state->bufferPos == state->currentLimit); +} + +void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, + int32_t value) { + if (state->lastTag != value) { + RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read"); + } +} + +@implementation GPBCodedInputStream + ++ (instancetype)streamWithData:(NSData *)data { + return [[[self alloc] initWithData:data] autorelease]; +} + +- (instancetype)initWithData:(NSData *)data { + if ((self = [super init])) { +#ifdef DEBUG + NSCAssert([self class] == [GPBCodedInputStream class], + @"Subclassing of GPBCodedInputStream is not allowed."); +#endif + buffer_ = [data retain]; + state_.bytes = (const uint8_t *)[data bytes]; + state_.bufferSize = [data length]; + state_.currentLimit = state_.bufferSize; + } + return self; +} + +- (void)dealloc { + [buffer_ release]; + [super dealloc]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (int32_t)readTag { + return GPBCodedInputStreamReadTag(&state_); +} + +- (void)checkLastTagWas:(int32_t)value { + GPBCodedInputStreamCheckLastTagWas(&state_, value); +} + +- (BOOL)skipField:(int32_t)tag { + NSAssert(GPBWireFormatIsValidTag(tag), @"Invalid tag"); + switch (GPBWireFormatGetTagWireType(tag)) { + case GPBWireFormatVarint: + GPBCodedInputStreamReadInt32(&state_); + return YES; + case GPBWireFormatFixed64: + SkipRawData(&state_, sizeof(int64_t)); + return YES; + case GPBWireFormatLengthDelimited: + SkipRawData(&state_, ReadRawVarint32(&state_)); + return YES; + case GPBWireFormatStartGroup: + [self skipMessage]; + GPBCodedInputStreamCheckLastTagWas( + &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag), + GPBWireFormatEndGroup)); + return YES; + case GPBWireFormatEndGroup: + return NO; + case GPBWireFormatFixed32: + SkipRawData(&state_, sizeof(int32_t)); + return YES; + } +} + +- (void)skipMessage { + while (YES) { + int32_t tag = GPBCodedInputStreamReadTag(&state_); + if (tag == 0 || ![self skipField:tag]) { + return; + } + } +} + +- (BOOL)isAtEnd { + return GPBCodedInputStreamIsAtEnd(&state_); +} + +- (size_t)position { + return state_.bufferPos; +} + +- (size_t)pushLimit:(size_t)byteLimit { + return GPBCodedInputStreamPushLimit(&state_, byteLimit); +} + +- (void)popLimit:(size_t)oldLimit { + GPBCodedInputStreamPopLimit(&state_, oldLimit); +} + +- (double)readDouble { + return GPBCodedInputStreamReadDouble(&state_); +} + +- (float)readFloat { + return GPBCodedInputStreamReadFloat(&state_); +} + +- (uint64_t)readUInt64 { + return GPBCodedInputStreamReadUInt64(&state_); +} + +- (int64_t)readInt64 { + return GPBCodedInputStreamReadInt64(&state_); +} + +- (int32_t)readInt32 { + return GPBCodedInputStreamReadInt32(&state_); +} + +- (uint64_t)readFixed64 { + return GPBCodedInputStreamReadFixed64(&state_); +} + +- (uint32_t)readFixed32 { + return GPBCodedInputStreamReadFixed32(&state_); +} + +- (BOOL)readBool { + return GPBCodedInputStreamReadBool(&state_); +} + +- (NSString *)readString { + return [GPBCodedInputStreamReadRetainedString(&state_) autorelease]; +} + +- (void)readGroup:(int32_t)fieldNumber + message:(GPBMessage *)message + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + CheckRecursionLimit(&state_); + ++state_.recursionDepth; + [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; + GPBCodedInputStreamCheckLastTagWas( + &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); + --state_.recursionDepth; +} + +- (void)readUnknownGroup:(int32_t)fieldNumber + message:(GPBUnknownFieldSet *)message { + CheckRecursionLimit(&state_); + ++state_.recursionDepth; + [message mergeFromCodedInputStream:self]; + GPBCodedInputStreamCheckLastTagWas( + &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); + --state_.recursionDepth; +} + +- (void)readMessage:(GPBMessage *)message + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + CheckRecursionLimit(&state_); + int32_t length = ReadRawVarint32(&state_); + size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); + ++state_.recursionDepth; + [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; + GPBCodedInputStreamCheckLastTagWas(&state_, 0); + --state_.recursionDepth; + GPBCodedInputStreamPopLimit(&state_, oldLimit); +} + +- (void)readMapEntry:(id)mapDictionary + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + field:(GPBFieldDescriptor *)field + parentMessage:(GPBMessage *)parentMessage { + CheckRecursionLimit(&state_); + int32_t length = ReadRawVarint32(&state_); + size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); + ++state_.recursionDepth; + GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field, + parentMessage); + GPBCodedInputStreamCheckLastTagWas(&state_, 0); + --state_.recursionDepth; + GPBCodedInputStreamPopLimit(&state_, oldLimit); +} + +- (NSData *)readBytes { + return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease]; +} + +- (uint32_t)readUInt32 { + return GPBCodedInputStreamReadUInt32(&state_); +} + +- (int32_t)readEnum { + return GPBCodedInputStreamReadEnum(&state_); +} + +- (int32_t)readSFixed32 { + return GPBCodedInputStreamReadSFixed32(&state_); +} + +- (int64_t)readSFixed64 { + return GPBCodedInputStreamReadSFixed64(&state_); +} + +- (int32_t)readSInt32 { + return GPBCodedInputStreamReadSInt32(&state_); +} + +- (int64_t)readSInt64 { + return GPBCodedInputStreamReadSInt64(&state_); +} + +#pragma clang diagnostic pop + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream_PackagePrivate.h new file mode 100644 index 0000000..43ec6e7 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedInputStream_PackagePrivate.h @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is private to the ProtobolBuffers library and must NOT be +// included by any sources outside this library. The contents of this file are +// subject to change at any time without notice. + +#import "GPBCodedInputStream.h" + +@class GPBUnknownFieldSet; +@class GPBFieldDescriptor; + +typedef struct GPBCodedInputStreamState { + const uint8_t *bytes; + size_t bufferSize; + size_t bufferPos; + + // For parsing subsections of an input stream you can put a hard limit on + // how much should be read. Normally the limit is the end of the stream, + // but you can adjust it to anywhere, and if you hit it you will be at the + // end of the stream, until you adjust the limit. + size_t currentLimit; + int32_t lastTag; + NSUInteger recursionDepth; +} GPBCodedInputStreamState; + +@interface GPBCodedInputStream () { + @package + struct GPBCodedInputStreamState state_; + NSData *buffer_; +} + +// Group support is deprecated, so we hide this interface from users, but +// support for older data. +- (void)readGroup:(int32_t)fieldNumber + message:(GPBMessage *)message + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + +// Reads a group field value from the stream and merges it into the given +// UnknownFieldSet. +- (void)readUnknownGroup:(int32_t)fieldNumber + message:(GPBUnknownFieldSet *)message; + +// Reads a map entry. +- (void)readMapEntry:(id)mapDictionary + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + field:(GPBFieldDescriptor *)field + parentMessage:(GPBMessage *)parentMessage; +@end + +CF_EXTERN_C_BEGIN + +int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state); + +double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state); +float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state); +uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state); +uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state); +int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state); +uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state); +uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state); +int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state); +int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state); +BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state); +NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state) + __attribute((ns_returns_retained)); +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) + __attribute((ns_returns_retained)); +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( + GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); + +size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, + size_t byteLimit); +void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, + size_t oldLimit); +size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state); +BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state); +void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, + int32_t value); + +CF_EXTERN_C_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.h new file mode 100644 index 0000000..23c404b --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.h @@ -0,0 +1,748 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" +#import "GPBWireFormat.h" + +@class GPBBoolArray; +@class GPBDoubleArray; +@class GPBEnumArray; +@class GPBFloatArray; +@class GPBMessage; +@class GPBInt32Array; +@class GPBInt64Array; +@class GPBUInt32Array; +@class GPBUInt64Array; +@class GPBUnknownFieldSet; + +NS_ASSUME_NONNULL_BEGIN + +/** + * @c GPBCodedOutputStream exception names. + **/ +extern NSString *const GPBCodedOutputStreamException_OutOfSpace; +extern NSString *const GPBCodedOutputStreamException_WriteFailed; + +/** + * Writes out protocol message fields. + * + * The common uses of protocol buffers shouldn't need to use this class. + * GPBMessage's provide a -data method that will serialize the message for you. + * + * @note Any -write* api can raise the GPBCodedOutputStreamException_* + * exceptions. + * + * @note Subclassing of GPBCodedOutputStream is NOT supported. + **/ +@interface GPBCodedOutputStream : NSObject + +/** + * Creates a stream to fill in the given data. Data must be sized to fit or + * an error will be raised when out of space. + * + * @param data The data where the stream will be written to. + * + * @return A newly instanced GPBCodedOutputStream. + **/ ++ (instancetype)streamWithData:(NSMutableData *)data; + +/** + * Creates a stream to write into the given NSOutputStream. + * + * @param output The output stream where the stream will be written to. + * + * @return A newly instanced GPBCodedOutputStream. + **/ ++ (instancetype)streamWithOutputStream:(NSOutputStream *)output; + +/** + * Initializes a stream to fill in the given data. Data must be sized to fit + * or an error will be raised when out of space. + * + * @param data The data where the stream will be written to. + * + * @return A newly initialized GPBCodedOutputStream. + **/ +- (instancetype)initWithData:(NSMutableData *)data; + +/** + * Initializes a stream to write into the given @c NSOutputStream. + * + * @param output The output stream where the stream will be written to. + * + * @return A newly initialized GPBCodedOutputStream. + **/ +- (instancetype)initWithOutputStream:(NSOutputStream *)output; + +/** + * Flush any buffered data out. + **/ +- (void)flush; + +/** + * Write the raw byte out. + * + * @param value The value to write out. + **/ +- (void)writeRawByte:(uint8_t)value; + +/** + * Write the tag for the given field number and wire format. + * + * @param fieldNumber The field number. + * @param format The wire format the data for the field will be in. + **/ +- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format; + +/** + * Write a 32bit value out in little endian format. + * + * @param value The value to write out. + **/ +- (void)writeRawLittleEndian32:(int32_t)value; +/** + * Write a 64bit value out in little endian format. + * + * @param value The value to write out. + **/ +- (void)writeRawLittleEndian64:(int64_t)value; + +/** + * Write a 32bit value out in varint format. + * + * @param value The value to write out. + **/ +- (void)writeRawVarint32:(int32_t)value; +/** + * Write a 64bit value out in varint format. + * + * @param value The value to write out. + **/ +- (void)writeRawVarint64:(int64_t)value; + +/** + * Write a size_t out as a 32bit varint value. + * + * @note This will truncate 64 bit values to 32. + * + * @param value The value to write out. + **/ +- (void)writeRawVarintSizeTAs32:(size_t)value; + +/** + * Writes the contents of an NSData out. + * + * @param data The data to write out. + **/ +- (void)writeRawData:(NSData *)data; +/** + * Writes out the given data. + * + * @param data The data blob to write out. + * @param offset The offset into the blob to start writing out. + * @param length The number of bytes from the blob to write out. + **/ +- (void)writeRawPtr:(const void *)data + offset:(size_t)offset + length:(size_t)length; + +//%PDDM-EXPAND _WRITE_DECLS() +// This block of code is generated, do not edit it directly. + +/** + * Write a double for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeDouble:(int32_t)fieldNumber value:(double)value; +/** + * Write a packed array of double for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag; +/** + * Write a double without any tag. + * + * @param value The value to write out. + **/ +- (void)writeDoubleNoTag:(double)value; + +/** + * Write a float for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeFloat:(int32_t)fieldNumber value:(float)value; +/** + * Write a packed array of float for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag; +/** + * Write a float without any tag. + * + * @param value The value to write out. + **/ +- (void)writeFloatNoTag:(float)value; + +/** + * Write a uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value; +/** + * Write a packed array of uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a uint64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeUInt64NoTag:(uint64_t)value; + +/** + * Write a int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value; +/** + * Write a packed array of int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a int64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeInt64NoTag:(int64_t)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeInt32NoTag:(int32_t)value; + +/** + * Write a uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value; +/** + * Write a packed array of uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a uint32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeUInt32NoTag:(uint32_t)value; + +/** + * Write a uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value; +/** + * Write a packed array of uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a uint64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeFixed64NoTag:(uint64_t)value; + +/** + * Write a uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value; +/** + * Write a packed array of uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a uint32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeFixed32NoTag:(uint32_t)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSInt32NoTag:(int32_t)value; + +/** + * Write a int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value; +/** + * Write a packed array of int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a int64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSInt64NoTag:(int64_t)value; + +/** + * Write a int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value; +/** + * Write a packed array of int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a int64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSFixed64NoTag:(int64_t)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSFixed32NoTag:(int32_t)value; + +/** + * Write a BOOL for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value; +/** + * Write a packed array of BOOL for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag; +/** + * Write a BOOL without any tag. + * + * @param value The value to write out. + **/ +- (void)writeBoolNoTag:(BOOL)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeEnumNoTag:(int32_t)value; + +/** + * Write a NSString for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeString:(int32_t)fieldNumber value:(NSString *)value; +/** + * Write an array of NSString for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a NSString without any tag. + * + * @param value The value to write out. + **/ +- (void)writeStringNoTag:(NSString *)value; + +/** + * Write a GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value; +/** + * Write an array of GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a GPBMessage without any tag. + * + * @param value The value to write out. + **/ +- (void)writeMessageNoTag:(GPBMessage *)value; + +/** + * Write a NSData for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value; +/** + * Write an array of NSData for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a NSData without any tag. + * + * @param value The value to write out. + **/ +- (void)writeBytesNoTag:(NSData *)value; + +/** + * Write a GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeGroup:(int32_t)fieldNumber + value:(GPBMessage *)value; +/** + * Write an array of GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a GPBMessage without any tag (but does write the endGroup tag). + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeGroupNoTag:(int32_t)fieldNumber + value:(GPBMessage *)value; + +/** + * Write a GPBUnknownFieldSet for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUnknownGroup:(int32_t)fieldNumber + value:(GPBUnknownFieldSet *)value; +/** + * Write an array of GPBUnknownFieldSet for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag). + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber + value:(GPBUnknownFieldSet *)value; + +//%PDDM-EXPAND-END _WRITE_DECLS() + +/** +Write a MessageSet extension field to the stream. For historical reasons, +the wire format differs from normal fields. + +@param fieldNumber The extension field number to write out. +@param value The message from where to get the extension. +*/ +- (void)writeMessageSetExtension:(int32_t)fieldNumber value:(GPBMessage *)value; + +/** +Write an unparsed MessageSet extension field to the stream. For historical +reasons, the wire format differs from normal fields. + +@param fieldNumber The extension field number to write out. +@param value The raw message from where to get the extension. +*/ +- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value; + +@end + +NS_ASSUME_NONNULL_END + +// Write methods for types that can be in packed arrays. +//%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE) +//%/** +//% * Write a TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value; +//%/** +//% * Write a packed array of TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the values. +//% * @param values The values to write out. +//% * @param tag The tag assigned to the values. +//% **/ +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values +//% NAME$S tag:(uint32_t)tag; +//%/** +//% * Write a TYPE without any tag. +//% * +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME##NoTag:(TYPE)value; +//% +// Write methods for types that aren't in packed arrays. +//%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE) +//%/** +//% * Write a TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE *)value; +//%/** +//% * Write an array of TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the values. +//% * @param values The values to write out. +//% **/ +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values; +//%/** +//% * Write a TYPE without any tag. +//% * +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME##NoTag:(TYPE *)value; +//% +// Special write methods for Groups. +//%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE) +//%/** +//% * Write a TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME:(int32_t)fieldNumber +//% NAME$S value:(TYPE *)value; +//%/** +//% * Write an array of TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the values. +//% * @param values The values to write out. +//% **/ +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values; +//%/** +//% * Write a TYPE without any tag (but does write the endGroup tag). +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME##NoTag:(int32_t)fieldNumber +//% NAME$S value:(TYPE *)value; +//% + +// One macro to hide it all up above. +//%PDDM-DEFINE _WRITE_DECLS() +//%_WRITE_PACKABLE_DECLS(Double, Double, double) +//%_WRITE_PACKABLE_DECLS(Float, Float, float) +//%_WRITE_PACKABLE_DECLS(UInt64, UInt64, uint64_t) +//%_WRITE_PACKABLE_DECLS(Int64, Int64, int64_t) +//%_WRITE_PACKABLE_DECLS(Int32, Int32, int32_t) +//%_WRITE_PACKABLE_DECLS(UInt32, UInt32, uint32_t) +//%_WRITE_PACKABLE_DECLS(Fixed64, UInt64, uint64_t) +//%_WRITE_PACKABLE_DECLS(Fixed32, UInt32, uint32_t) +//%_WRITE_PACKABLE_DECLS(SInt32, Int32, int32_t) +//%_WRITE_PACKABLE_DECLS(SInt64, Int64, int64_t) +//%_WRITE_PACKABLE_DECLS(SFixed64, Int64, int64_t) +//%_WRITE_PACKABLE_DECLS(SFixed32, Int32, int32_t) +//%_WRITE_PACKABLE_DECLS(Bool, Bool, BOOL) +//%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t) +//%_WRITE_UNPACKABLE_DECLS(String, NSString) +//%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage) +//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData) +//%_WRITE_GROUP_DECLS(Group, GPBMessage) +//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.m new file mode 100644 index 0000000..b846c2f --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.m @@ -0,0 +1,1210 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBCodedOutputStream_PackagePrivate.h" + +#import + +#import "GPBArray.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +// These values are the existing values so as not to break any code that might +// have already been inspecting them when they weren't documented/exposed. +NSString *const GPBCodedOutputStreamException_OutOfSpace = @"OutOfSpace"; +NSString *const GPBCodedOutputStreamException_WriteFailed = @"WriteFailed"; + +// Structure for containing state of a GPBCodedInputStream. Brought out into +// a struct so that we can inline several common functions instead of dealing +// with overhead of ObjC dispatch. +typedef struct GPBOutputBufferState { + uint8_t *bytes; + size_t size; + size_t position; + NSOutputStream *output; +} GPBOutputBufferState; + +@implementation GPBCodedOutputStream { + GPBOutputBufferState state_; + NSMutableData *buffer_; +} + +static const int32_t LITTLE_ENDIAN_32_SIZE = sizeof(uint32_t); +static const int32_t LITTLE_ENDIAN_64_SIZE = sizeof(uint64_t); + +// Internal helper that writes the current buffer to the output. The +// buffer position is reset to its initial value when this returns. +static void GPBRefreshBuffer(GPBOutputBufferState *state) { + if (state->output == nil) { + // We're writing to a single buffer. + [NSException raise:GPBCodedOutputStreamException_OutOfSpace format:@""]; + } + if (state->position != 0) { + NSInteger written = + [state->output write:state->bytes maxLength:state->position]; + if (written != (NSInteger)state->position) { + [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""]; + } + state->position = 0; + } +} + +static void GPBWriteRawByte(GPBOutputBufferState *state, uint8_t value) { + if (state->position == state->size) { + GPBRefreshBuffer(state); + } + state->bytes[state->position++] = value; +} + +static void GPBWriteRawVarint32(GPBOutputBufferState *state, int32_t value) { + while (YES) { + if ((value & ~0x7F) == 0) { + uint8_t val = (uint8_t)value; + GPBWriteRawByte(state, val); + return; + } else { + GPBWriteRawByte(state, (value & 0x7F) | 0x80); + value = GPBLogicalRightShift32(value, 7); + } + } +} + +static void GPBWriteRawVarint64(GPBOutputBufferState *state, int64_t value) { + while (YES) { + if ((value & ~0x7FL) == 0) { + uint8_t val = (uint8_t)value; + GPBWriteRawByte(state, val); + return; + } else { + GPBWriteRawByte(state, ((int32_t)value & 0x7F) | 0x80); + value = GPBLogicalRightShift64(value, 7); + } + } +} + +static void GPBWriteInt32NoTag(GPBOutputBufferState *state, int32_t value) { + if (value >= 0) { + GPBWriteRawVarint32(state, value); + } else { + // Must sign-extend + GPBWriteRawVarint64(state, value); + } +} + +static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber, + uint32_t value) { + GPBWriteTagWithFormat(state, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint32(state, value); +} + +static void GPBWriteTagWithFormat(GPBOutputBufferState *state, + uint32_t fieldNumber, GPBWireFormat format) { + GPBWriteRawVarint32(state, GPBWireFormatMakeTag(fieldNumber, format)); +} + +static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state, + int32_t value) { + GPBWriteRawByte(state, (value)&0xFF); + GPBWriteRawByte(state, (value >> 8) & 0xFF); + GPBWriteRawByte(state, (value >> 16) & 0xFF); + GPBWriteRawByte(state, (value >> 24) & 0xFF); +} + +static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, + int64_t value) { + GPBWriteRawByte(state, (int32_t)(value)&0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 8) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 16) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 24) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 32) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 40) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 48) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF); +} + +- (void)dealloc { + [self flush]; + [state_.output close]; + [state_.output release]; + [buffer_ release]; + + [super dealloc]; +} + +- (instancetype)initWithOutputStream:(NSOutputStream *)output { + NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE]; + return [self initWithOutputStream:output data:data]; +} + +- (instancetype)initWithData:(NSMutableData *)data { + return [self initWithOutputStream:nil data:data]; +} + +// This initializer isn't exposed, but it is the designated initializer. +// Setting OutputStream and NSData is to control the buffering behavior/size +// of the work, but that is more obvious via the bufferSize: version. +- (instancetype)initWithOutputStream:(NSOutputStream *)output + data:(NSMutableData *)data { + if ((self = [super init])) { + buffer_ = [data retain]; + state_.bytes = [data mutableBytes]; + state_.size = [data length]; + state_.output = [output retain]; + [state_.output open]; + } + return self; +} + ++ (instancetype)streamWithOutputStream:(NSOutputStream *)output { + NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE]; + return [[[self alloc] initWithOutputStream:output + data:data] autorelease]; +} + ++ (instancetype)streamWithData:(NSMutableData *)data { + return [[[self alloc] initWithData:data] autorelease]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (void)writeDoubleNoTag:(double)value { + GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value)); +} + +- (void)writeDouble:(int32_t)fieldNumber value:(double)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64); + GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value)); +} + +- (void)writeFloatNoTag:(float)value { + GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value)); +} + +- (void)writeFloat:(int32_t)fieldNumber value:(float)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32); + GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value)); +} + +- (void)writeUInt64NoTag:(uint64_t)value { + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeInt64NoTag:(int64_t)value { + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeInt32NoTag:(int32_t)value { + GPBWriteInt32NoTag(&state_, value); +} + +- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteInt32NoTag(&state_, value); +} + +- (void)writeFixed64NoTag:(uint64_t)value { + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64); + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeFixed32NoTag:(uint32_t)value { + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32); + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeBoolNoTag:(BOOL)value { + GPBWriteRawByte(&state_, (value ? 1 : 0)); +} + +- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawByte(&state_, (value ? 1 : 0)); +} + +- (void)writeStringNoTag:(const NSString *)value { + size_t length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + GPBWriteRawVarint32(&state_, (int32_t)length); + if (length == 0) { + return; + } + + const char *quickString = + CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8); + + // Fast path: Most strings are short, if the buffer already has space, + // add to it directly. + NSUInteger bufferBytesLeft = state_.size - state_.position; + if (bufferBytesLeft >= length) { + NSUInteger usedBufferLength = 0; + BOOL result; + if (quickString != NULL) { + memcpy(state_.bytes + state_.position, quickString, length); + usedBufferLength = length; + result = YES; + } else { + result = [value getBytes:state_.bytes + state_.position + maxLength:bufferBytesLeft + usedLength:&usedBufferLength + encoding:NSUTF8StringEncoding + options:(NSStringEncodingConversionOptions)0 + range:NSMakeRange(0, [value length]) + remainingRange:NULL]; + } + if (result) { + NSAssert2((usedBufferLength == length), + @"Our UTF8 calc was wrong? %tu vs %zd", usedBufferLength, + length); + state_.position += usedBufferLength; + return; + } + } else if (quickString != NULL) { + [self writeRawPtr:quickString offset:0 length:length]; + } else { + // Slow path: just get it as data and write it out. + NSData *utf8Data = [value dataUsingEncoding:NSUTF8StringEncoding]; + NSAssert2(([utf8Data length] == length), + @"Strings UTF8 length was wrong? %tu vs %zd", [utf8Data length], + length); + [self writeRawData:utf8Data]; + } +} + +- (void)writeString:(int32_t)fieldNumber value:(NSString *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); + [self writeStringNoTag:value]; +} + +- (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value { + [value writeToCodedOutputStream:self]; + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup); +} + +- (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup); + [self writeGroupNoTag:fieldNumber value:value]; +} + +- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber + value:(const GPBUnknownFieldSet *)value { + [value writeToCodedOutputStream:self]; + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup); +} + +- (void)writeUnknownGroup:(int32_t)fieldNumber + value:(GPBUnknownFieldSet *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup); + [self writeUnknownGroupNoTag:fieldNumber value:value]; +} + +- (void)writeMessageNoTag:(GPBMessage *)value { + GPBWriteRawVarint32(&state_, (int32_t)[value serializedSize]); + [value writeToCodedOutputStream:self]; +} + +- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); + [self writeMessageNoTag:value]; +} + +- (void)writeBytesNoTag:(NSData *)value { + GPBWriteRawVarint32(&state_, (int32_t)[value length]); + [self writeRawData:value]; +} + +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); + [self writeBytesNoTag:value]; +} + +- (void)writeUInt32NoTag:(uint32_t)value { + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value { + GPBWriteUInt32(&state_, fieldNumber, value); +} + +- (void)writeEnumNoTag:(int32_t)value { + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeSFixed32NoTag:(int32_t)value { + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32); + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeSFixed64NoTag:(int64_t)value { + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64); + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeSInt32NoTag:(int32_t)value { + GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value)); +} + +- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value)); +} + +- (void)writeSInt64NoTag:(int64_t)value { + GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value)); +} + +- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value)); +} + +//%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME) +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values +//% NAME$S tag:(uint32_t)tag { +//% if (tag != 0) { +//% if (values.count == 0) return; +//% __block size_t dataSize = 0; +//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { +//%#pragma unused(idx, stop) +//% dataSize += GPBCompute##NAME##SizeNoTag(value); +//% }]; +//% GPBWriteRawVarint32(&state_, tag); +//% GPBWriteRawVarint32(&state_, (int32_t)dataSize); +//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { +//%#pragma unused(idx, stop) +//% [self write##NAME##NoTag:value]; +//% }]; +//% } else { +//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { +//%#pragma unused(idx, stop) +//% [self write##NAME:fieldNumber value:value]; +//% }]; +//% } +//%} +//% +//%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE) +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values { +//% for (TYPE *value in values) { +//% [self write##NAME:fieldNumber value:value]; +//% } +//%} +//% +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, ) +// This block of code is generated, do not edit it directly. + +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeDoubleSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeDoubleNoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeDouble:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, ) +// This block of code is generated, do not edit it directly. + +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeFloatSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFloatNoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFloat:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeUInt64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeInt64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeInt32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeUInt32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeFixed64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeFixed32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSInt32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSInt64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSFixed64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSFixed32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, ) +// This block of code is generated, do not edit it directly. + +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeBoolSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeBoolNoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeBool:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw) +// This block of code is generated, do not edit it directly. + +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeEnumSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeEnumNoTag:value]; + }]; + } else { + [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeEnum:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString) +// This block of code is generated, do not edit it directly. + +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values { + for (NSString *value in values) { + [self writeString:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage) +// This block of code is generated, do not edit it directly. + +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values { + for (GPBMessage *value in values) { + [self writeMessage:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData) +// This block of code is generated, do not edit it directly. + +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values { + for (NSData *value in values) { + [self writeBytes:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage) +// This block of code is generated, do not edit it directly. + +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { + for (GPBMessage *value in values) { + [self writeGroup:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet) +// This block of code is generated, do not edit it directly. + +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { + for (GPBUnknownFieldSet *value in values) { + [self writeUnknownGroup:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND-END (19 expansions) + +- (void)writeMessageSetExtension:(int32_t)fieldNumber + value:(GPBMessage *)value { + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatStartGroup); + GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber); + [self writeMessage:GPBWireFormatMessageSetMessage value:value]; + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatEndGroup); +} + +- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value { + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatStartGroup); + GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber); + [self writeBytes:GPBWireFormatMessageSetMessage value:value]; + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatEndGroup); +} + +- (void)flush { + if (state_.output != nil) { + GPBRefreshBuffer(&state_); + } +} + +- (void)writeRawByte:(uint8_t)value { + GPBWriteRawByte(&state_, value); +} + +- (void)writeRawData:(const NSData *)data { + [self writeRawPtr:[data bytes] offset:0 length:[data length]]; +} + +- (void)writeRawPtr:(const void *)value + offset:(size_t)offset + length:(size_t)length { + if (value == nil || length == 0) { + return; + } + + NSUInteger bufferLength = state_.size; + NSUInteger bufferBytesLeft = bufferLength - state_.position; + if (bufferBytesLeft >= length) { + // We have room in the current buffer. + memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, length); + state_.position += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + size_t bytesWritten = bufferBytesLeft; + memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, + bytesWritten); + offset += bytesWritten; + length -= bytesWritten; + state_.position = bufferLength; + GPBRefreshBuffer(&state_); + bufferLength = state_.size; + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + if (length <= bufferLength) { + // Fits in new buffer. + memcpy(state_.bytes, ((uint8_t *)value) + offset, length); + state_.position = length; + } else { + // Write is very big. Let's do it all at once. + NSInteger written = [state_.output write:((uint8_t *)value) + offset maxLength:length]; + if (written != (NSInteger)length) { + [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""]; + } + } + } +} + +- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format { + GPBWriteTagWithFormat(&state_, fieldNumber, format); +} + +- (void)writeRawVarint32:(int32_t)value { + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeRawVarintSizeTAs32:(size_t)value { + // Note the truncation. + GPBWriteRawVarint32(&state_, (int32_t)value); +} + +- (void)writeRawVarint64:(int64_t)value { + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeRawLittleEndian32:(int32_t)value { + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeRawLittleEndian64:(int64_t)value { + GPBWriteRawLittleEndian64(&state_, value); +} + +#pragma clang diagnostic pop + +@end + +size_t GPBComputeDoubleSizeNoTag(Float64 value) { +#pragma unused(value) + return LITTLE_ENDIAN_64_SIZE; +} + +size_t GPBComputeFloatSizeNoTag(Float32 value) { +#pragma unused(value) + return LITTLE_ENDIAN_32_SIZE; +} + +size_t GPBComputeUInt64SizeNoTag(uint64_t value) { + return GPBComputeRawVarint64Size(value); +} + +size_t GPBComputeInt64SizeNoTag(int64_t value) { + return GPBComputeRawVarint64Size(value); +} + +size_t GPBComputeInt32SizeNoTag(int32_t value) { + if (value >= 0) { + return GPBComputeRawVarint32Size(value); + } else { + // Must sign-extend. + return 10; + } +} + +size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) { + return GPBComputeInt32SizeNoTag((int32_t)value); +} + +size_t GPBComputeFixed64SizeNoTag(uint64_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_64_SIZE; +} + +size_t GPBComputeFixed32SizeNoTag(uint32_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_32_SIZE; +} + +size_t GPBComputeBoolSizeNoTag(BOOL value) { +#pragma unused(value) + return 1; +} + +size_t GPBComputeStringSizeNoTag(NSString *value) { + NSUInteger length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + return GPBComputeRawVarint32SizeForInteger(length) + length; +} + +size_t GPBComputeGroupSizeNoTag(GPBMessage *value) { + return [value serializedSize]; +} + +size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) { + return value.serializedSize; +} + +size_t GPBComputeMessageSizeNoTag(GPBMessage *value) { + size_t size = [value serializedSize]; + return GPBComputeRawVarint32SizeForInteger(size) + size; +} + +size_t GPBComputeBytesSizeNoTag(NSData *value) { + NSUInteger valueLength = [value length]; + return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength; +} + +size_t GPBComputeUInt32SizeNoTag(int32_t value) { + return GPBComputeRawVarint32Size(value); +} + +size_t GPBComputeEnumSizeNoTag(int32_t value) { + return GPBComputeRawVarint32Size(value); +} + +size_t GPBComputeSFixed32SizeNoTag(int32_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_32_SIZE; +} + +size_t GPBComputeSFixed64SizeNoTag(int64_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_64_SIZE; +} + +size_t GPBComputeSInt32SizeNoTag(int32_t value) { + return GPBComputeRawVarint32Size(GPBEncodeZigZag32(value)); +} + +size_t GPBComputeSInt64SizeNoTag(int64_t value) { + return GPBComputeRawVarint64Size(GPBEncodeZigZag64(value)); +} + +size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeDoubleSizeNoTag(value); +} + +size_t GPBComputeFloatSize(int32_t fieldNumber, float value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeFloatSizeNoTag(value); +} + +size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeUInt64SizeNoTag(value); +} + +size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeInt64SizeNoTag(value); +} + +size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeInt32SizeNoTag(value); +} + +size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeFixed64SizeNoTag(value); +} + +size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeFixed32SizeNoTag(value); +} + +size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeBoolSizeNoTag(value); +} + +size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeStringSizeNoTag(value); +} + +size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) { + return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value); +} + +size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, + GPBUnknownFieldSet *value) { + return GPBComputeTagSize(fieldNumber) * 2 + + GPBComputeUnknownGroupSizeNoTag(value); +} + +size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value); +} + +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value); +} + +size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeUInt32SizeNoTag(value); +} + +size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeEnumSizeNoTag(value); +} + +size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed32SizeNoTag(value); +} + +size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed64SizeNoTag(value); +} + +size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeSInt32SizeNoTag(value); +} + +size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) { + return GPBComputeTagSize(fieldNumber) + + GPBComputeRawVarint64Size(GPBEncodeZigZag64(value)); +} + +size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, + GPBMessage *value) { + return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 + + GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) + + GPBComputeMessageSize(GPBWireFormatMessageSetMessage, value); +} + +size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, + NSData *value) { + return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 + + GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) + + GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value); +} + +size_t GPBComputeTagSize(int32_t fieldNumber) { + return GPBComputeRawVarint32Size( + GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint)); +} + +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) { + size_t result = GPBComputeTagSize(field_number); + if (dataType == GPBDataTypeGroup) { + // Groups have both a start and an end tag. + return result * 2; + } else { + return result; + } +} + +size_t GPBComputeRawVarint32Size(int32_t value) { + // value is treated as unsigned, so it won't be sign-extended if negative. + if ((value & (0xffffffff << 7)) == 0) return 1; + if ((value & (0xffffffff << 14)) == 0) return 2; + if ((value & (0xffffffff << 21)) == 0) return 3; + if ((value & (0xffffffff << 28)) == 0) return 4; + return 5; +} + +size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) { + // Note the truncation. + return GPBComputeRawVarint32Size((int32_t)value); +} + +size_t GPBComputeRawVarint64Size(int64_t value) { + if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; + if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; + if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; + if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; + if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; + if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; + if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; + if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; + if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; + return 10; +} diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream_PackagePrivate.h new file mode 100644 index 0000000..2e7bb4c --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBCodedOutputStream_PackagePrivate.h @@ -0,0 +1,126 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBCodedOutputStream.h" + +NS_ASSUME_NONNULL_BEGIN + +CF_EXTERN_C_BEGIN + +size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) + __attribute__((const)); +size_t GPBComputeFloatSize(int32_t fieldNumber, float value) + __attribute__((const)); +size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) + __attribute__((const)); +size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) + __attribute__((const)); +size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) + __attribute__((const)); +size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) + __attribute__((const)); +size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) + __attribute__((const)); +size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) + __attribute__((const)); +size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) + __attribute__((const)); +size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) + __attribute__((const)); +size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, + GPBUnknownFieldSet *value) + __attribute__((const)); +size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) + __attribute__((const)); +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) + __attribute__((const)); +size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) + __attribute__((const)); +size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) + __attribute__((const)); +size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) + __attribute__((const)); +size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) + __attribute__((const)); +size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) + __attribute__((const)); +size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const)); +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) + __attribute__((const)); + +size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const)); +size_t GPBComputeFloatSizeNoTag(float value) __attribute__((const)); +size_t GPBComputeUInt64SizeNoTag(uint64_t value) __attribute__((const)); +size_t GPBComputeInt64SizeNoTag(int64_t value) __attribute__((const)); +size_t GPBComputeInt32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeFixed64SizeNoTag(uint64_t value) __attribute__((const)); +size_t GPBComputeFixed32SizeNoTag(uint32_t value) __attribute__((const)); +size_t GPBComputeBoolSizeNoTag(BOOL value) __attribute__((const)); +size_t GPBComputeStringSizeNoTag(NSString *value) __attribute__((const)); +size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const)); +size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) + __attribute__((const)); +size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const)); +size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const)); +size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeEnumSizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeSFixed32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeSFixed64SizeNoTag(int64_t value) __attribute__((const)); +size_t GPBComputeSInt32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeSInt64SizeNoTag(int64_t value) __attribute__((const)); + +// Note that this will calculate the size of 64 bit values truncated to 32. +size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) __attribute__((const)); + +size_t GPBComputeRawVarint32Size(int32_t value) __attribute__((const)); +size_t GPBComputeRawVarint64Size(int64_t value) __attribute__((const)); + +// Note that this will calculate the size of 64 bit values truncated to 32. +size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) + __attribute__((const)); + +// Compute the number of bytes that would be needed to encode a +// MessageSet extension to the stream. For historical reasons, +// the wire format differs from normal fields. +size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, GPBMessage *value) + __attribute__((const)); + +// Compute the number of bytes that would be needed to encode an +// unparsed MessageSet extension field to the stream. For +// historical reasons, the wire format differs from normal fields. +size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value) + __attribute__((const)); + +size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) + __attribute__((const)); + +CF_EXTERN_C_END + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor.h new file mode 100644 index 0000000..292bce1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor.h @@ -0,0 +1,318 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" + +@class GPBEnumDescriptor; +@class GPBFieldDescriptor; +@class GPBFileDescriptor; +@class GPBOneofDescriptor; + +NS_ASSUME_NONNULL_BEGIN + +/** Syntax used in the proto file. */ +typedef NS_ENUM(uint8_t, GPBFileSyntax) { + /** Unknown syntax. */ + GPBFileSyntaxUnknown = 0, + /** Proto2 syntax. */ + GPBFileSyntaxProto2 = 2, + /** Proto3 syntax. */ + GPBFileSyntaxProto3 = 3, +}; + +/** Type of proto field. */ +typedef NS_ENUM(uint8_t, GPBFieldType) { + /** Optional/required field. Only valid for proto2 fields. */ + GPBFieldTypeSingle, + /** Repeated field. */ + GPBFieldTypeRepeated, + /** Map field. */ + GPBFieldTypeMap, +}; + +/** + * Describes a proto message. + **/ +@interface GPBDescriptor : NSObject + +/** Name of the message. */ +@property(nonatomic, readonly, copy) NSString *name; +/** Fields declared in the message. */ +@property(nonatomic, readonly, strong, nullable) NSArray *fields; +/** Oneofs declared in the message. */ +@property(nonatomic, readonly, strong, nullable) NSArray *oneofs; +/** Extension range declared for the message. */ +@property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges; +/** Number of extension ranges declared for the message. */ +@property(nonatomic, readonly) uint32_t extensionRangesCount; +/** Descriptor for the file where the message was defined. */ +@property(nonatomic, readonly, assign) GPBFileDescriptor *file; + +/** Whether the message is in wire format or not. */ +@property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat; +/** The class of this message. */ +@property(nonatomic, readonly) Class messageClass; +/** Containing message descriptor if this message is nested, or nil otherwise. */ +@property(readonly, nullable) GPBDescriptor *containingType; +/** + * Fully qualified name for this message (package.message). Can be nil if the + * value is unable to be computed. + */ +@property(readonly, nullable) NSString *fullName; + +/** + * Gets the field for the given number. + * + * @param fieldNumber The number for the field to get. + * + * @return The field descriptor for the given number, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; + +/** + * Gets the field for the given name. + * + * @param name The name for the field to get. + * + * @return The field descriptor for the given name, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name; + +/** + * Gets the oneof for the given name. + * + * @param name The name for the oneof to get. + * + * @return The oneof descriptor for the given name, or nil if not found. + **/ +- (nullable GPBOneofDescriptor *)oneofWithName:(NSString *)name; + +@end + +/** + * Describes a proto file. + **/ +@interface GPBFileDescriptor : NSObject + +/** The package declared in the proto file. */ +@property(nonatomic, readonly, copy) NSString *package; +/** The objc prefix declared in the proto file. */ +@property(nonatomic, readonly, copy, nullable) NSString *objcPrefix; +/** The syntax of the proto file. */ +@property(nonatomic, readonly) GPBFileSyntax syntax; + +@end + +/** + * Describes a oneof field. + **/ +@interface GPBOneofDescriptor : NSObject +/** Name of the oneof field. */ +@property(nonatomic, readonly) NSString *name; +/** Fields declared in the oneof. */ +@property(nonatomic, readonly) NSArray *fields; + +/** + * Gets the field for the given number. + * + * @param fieldNumber The number for the field to get. + * + * @return The field descriptor for the given number, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; + +/** + * Gets the field for the given name. + * + * @param name The name for the field to get. + * + * @return The field descriptor for the given name, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name; + +@end + +/** + * Describes a proto field. + **/ +@interface GPBFieldDescriptor : NSObject + +/** Name of the field. */ +@property(nonatomic, readonly, copy) NSString *name; +/** Number associated with the field. */ +@property(nonatomic, readonly) uint32_t number; +/** Data type contained in the field. */ +@property(nonatomic, readonly) GPBDataType dataType; +/** Whether it has a default value or not. */ +@property(nonatomic, readonly) BOOL hasDefaultValue; +/** Default value for the field. */ +@property(nonatomic, readonly) GPBGenericValue defaultValue; +/** Whether this field is required. Only valid for proto2 fields. */ +@property(nonatomic, readonly, getter=isRequired) BOOL required; +/** Whether this field is optional. */ +@property(nonatomic, readonly, getter=isOptional) BOOL optional; +/** Type of field (single, repeated, map). */ +@property(nonatomic, readonly) GPBFieldType fieldType; +/** Type of the key if the field is a map. The value's type is -fieldType. */ +@property(nonatomic, readonly) GPBDataType mapKeyDataType; +/** Whether the field is packable. */ +@property(nonatomic, readonly, getter=isPackable) BOOL packable; + +/** The containing oneof if this field is part of one, nil otherwise. */ +@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof; + +/** Class of the message if the field is of message type. */ +@property(nonatomic, readonly, assign, nullable) Class msgClass; + +/** Descriptor for the enum if this field is an enum. */ +@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor; + +/** + * Checks whether the given enum raw value is a valid enum value. + * + * @param value The raw enum value to check. + * + * @return YES if value is a valid enum raw value. + **/ +- (BOOL)isValidEnumValue:(int32_t)value; + +/** @return Name for the text format, or nil if not known. */ +- (nullable NSString *)textFormatName; + +@end + +/** + * Describes a proto enum. + **/ +@interface GPBEnumDescriptor : NSObject + +/** Name of the enum. */ +@property(nonatomic, readonly, copy) NSString *name; +/** Function that validates that raw values are valid enum values. */ +@property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier; + +/** + * Returns the enum value name for the given raw enum. + * + * Note that there can be more than one name corresponding to a given value + * if the allow_alias option is used. + * + * @param number The raw enum value. + * + * @return The first name that matches the enum value passed, or nil if not valid. + **/ +- (nullable NSString *)enumNameForValue:(int32_t)number; + +/** + * Gets the enum raw value for the given enum name. + * + * @param outValue A pointer where the value will be set. + * @param name The enum name for which to get the raw value. + * + * @return YES if a value was copied into the pointer, NO otherwise. + **/ +- (BOOL)getValue:(nullable int32_t *)outValue forEnumName:(NSString *)name; + +/** + * Returns the text format for the given raw enum value. + * + * @param number The raw enum value. + * + * @return The first text format name which matches the enum value, or nil if not valid. + **/ +- (nullable NSString *)textFormatNameForValue:(int32_t)number; + +/** + * Gets the enum raw value for the given text format name. + * + * @param outValue A pointer where the value will be set. + * @param textFormatName The text format name for which to get the raw value. + * + * @return YES if a value was copied into the pointer, NO otherwise. + **/ +- (BOOL)getValue:(nullable int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName; + +/** + * Gets the number of defined enum names. + * + * @return Count of the number of enum names, including any aliases. + */ +@property(nonatomic, readonly) uint32_t enumNameCount; + +/** + * Gets the enum name corresponding to the given index. + * + * @param index Index into the available names. The defined range is from 0 + * to self.enumNameCount - 1. + * + * @returns The enum name at the given index, or nil if the index is out of range. + */ +- (nullable NSString *)getEnumNameForIndex:(uint32_t)index; + +/** + * Gets the enum text format name corresponding to the given index. + * + * @param index Index into the available names. The defined range is from 0 + * to self.enumNameCount - 1. + * + * @returns The text format name at the given index, or nil if the index is out of range. + */ +- (nullable NSString *)getEnumTextFormatNameForIndex:(uint32_t)index; + +@end + +/** + * Describes a proto extension. + **/ +@interface GPBExtensionDescriptor : NSObject +/** Field number under which the extension is stored. */ +@property(nonatomic, readonly) uint32_t fieldNumber; +/** The containing message class, i.e. the class extended by this extension. */ +@property(nonatomic, readonly) Class containingMessageClass; +/** Data type contained in the extension. */ +@property(nonatomic, readonly) GPBDataType dataType; +/** Whether the extension is repeated. */ +@property(nonatomic, readonly, getter=isRepeated) BOOL repeated; +/** Whether the extension is packable. */ +@property(nonatomic, readonly, getter=isPackable) BOOL packable; +/** The class of the message if the extension is of message type. */ +@property(nonatomic, readonly, assign) Class msgClass; +/** The singleton name for the extension. */ +@property(nonatomic, readonly) NSString *singletonName; +/** The enum descriptor if the extension is of enum type. */ +@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor; +/** The default value for the extension. */ +@property(nonatomic, readonly, nullable) id defaultValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor.m new file mode 100644 index 0000000..41bf5ad --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor.m @@ -0,0 +1,1123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBDescriptor_PackagePrivate.h" + +#import + +#import "GPBUtilities_PackagePrivate.h" +#import "GPBWireFormat.h" +#import "GPBMessage_PackagePrivate.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +// The addresses of these variables are used as keys for objc_getAssociatedObject. +static const char kTextFormatExtraValueKey = 0; +static const char kParentClassNameValueKey = 0; +static const char kClassNameSuffixKey = 0; + +// Utility function to generate selectors on the fly. +static SEL SelFromStrings(const char *prefix, const char *middle, + const char *suffix, BOOL takesArg) { + if (prefix == NULL && suffix == NULL && !takesArg) { + return sel_getUid(middle); + } + const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; + const size_t middleLen = strlen(middle); + const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; + size_t totalLen = + prefixLen + middleLen + suffixLen + 1; // include space for null on end. + if (takesArg) { + totalLen += 1; + } + char buffer[totalLen]; + if (prefix != NULL) { + memcpy(buffer, prefix, prefixLen); + memcpy(buffer + prefixLen, middle, middleLen); + buffer[prefixLen] = (char)toupper(buffer[prefixLen]); + } else { + memcpy(buffer, middle, middleLen); + } + if (suffix != NULL) { + memcpy(buffer + prefixLen + middleLen, suffix, suffixLen); + } + if (takesArg) { + buffer[totalLen - 2] = ':'; + } + // Always null terminate it. + buffer[totalLen - 1] = 0; + + SEL result = sel_getUid(buffer); + return result; +} + +static NSArray *NewFieldsArrayForHasIndex(int hasIndex, + NSArray *allMessageFields) + __attribute__((ns_returns_retained)); + +static NSArray *NewFieldsArrayForHasIndex(int hasIndex, + NSArray *allMessageFields) { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (GPBFieldDescriptor *fieldDesc in allMessageFields) { + if (fieldDesc->description_->hasIndex == hasIndex) { + [result addObject:fieldDesc]; + } + } + return result; +} + +@implementation GPBDescriptor { + Class messageClass_; + GPBFileDescriptor *file_; + BOOL wireFormat_; +} + +@synthesize messageClass = messageClass_; +@synthesize fields = fields_; +@synthesize oneofs = oneofs_; +@synthesize extensionRanges = extensionRanges_; +@synthesize extensionRangesCount = extensionRangesCount_; +@synthesize file = file_; +@synthesize wireFormat = wireFormat_; + ++ (instancetype) + allocDescriptorForClass:(Class)messageClass + rootClass:(Class)rootClass + file:(GPBFileDescriptor *)file + fields:(void *)fieldDescriptions + fieldCount:(uint32_t)fieldCount + storageSize:(uint32_t)storageSize + flags:(GPBDescriptorInitializationFlags)flags { + // The rootClass is no longer used, but it is passed in to ensure it + // was started up during initialization also. + (void)rootClass; + NSMutableArray *fields = nil; + GPBFileSyntax syntax = file.syntax; + BOOL fieldsIncludeDefault = + (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; + + void *desc; + for (uint32_t i = 0; i < fieldCount; ++i) { + if (fields == nil) { + fields = [[NSMutableArray alloc] initWithCapacity:fieldCount]; + } + // Need correctly typed pointer for array indexing below to work. + if (fieldsIncludeDefault) { + GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions; + desc = &(fieldDescWithDefault[i]); + } else { + GPBMessageFieldDescription *fieldDesc = fieldDescriptions; + desc = &(fieldDesc[i]); + } + GPBFieldDescriptor *fieldDescriptor = + [[GPBFieldDescriptor alloc] initWithFieldDescription:desc + includesDefault:fieldsIncludeDefault + syntax:syntax]; + [fields addObject:fieldDescriptor]; + [fieldDescriptor release]; + } + + BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0; + GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass + file:file + fields:fields + storageSize:storageSize + wireFormat:wireFormat]; + [fields release]; + return descriptor; +} + +- (instancetype)initWithClass:(Class)messageClass + file:(GPBFileDescriptor *)file + fields:(NSArray *)fields + storageSize:(uint32_t)storageSize + wireFormat:(BOOL)wireFormat { + if ((self = [super init])) { + messageClass_ = messageClass; + file_ = file; + fields_ = [fields retain]; + storageSize_ = storageSize; + wireFormat_ = wireFormat; + } + return self; +} + +- (void)dealloc { + [fields_ release]; + [oneofs_ release]; + [super dealloc]; +} + +- (void)setupOneofs:(const char **)oneofNames + count:(uint32_t)count + firstHasIndex:(int32_t)firstHasIndex { + NSCAssert(firstHasIndex < 0, @"Should always be <0"); + NSMutableArray *oneofs = [[NSMutableArray alloc] initWithCapacity:count]; + for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) { + const char *name = oneofNames[i]; + NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_); + NSCAssert(fieldsForOneof.count > 0, + @"No fields for this oneof? (%s:%d)", name, hasIndex); + GPBOneofDescriptor *oneofDescriptor = + [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof]; + [oneofs addObject:oneofDescriptor]; + [oneofDescriptor release]; + [fieldsForOneof release]; + } + oneofs_ = oneofs; +} + +- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo { + // Extra info is a compile time option, so skip the work if not needed. + if (extraTextFormatInfo) { + NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo]; + for (GPBFieldDescriptor *fieldDescriptor in fields_) { + if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) { + objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey, + extraInfoValue, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + } + } +} + +- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count { + extensionRanges_ = ranges; + extensionRangesCount_ = count; +} + +- (void)setupContainingMessageClassName:(const char *)msgClassName { + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). + NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); + NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; + objc_setAssociatedObject(self, &kParentClassNameValueKey, + parentNameValue, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setupMessageClassNameSuffix:(NSString *)suffix { + if (suffix.length) { + objc_setAssociatedObject(self, &kClassNameSuffixKey, + suffix, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } +} + +- (NSString *)name { + return NSStringFromClass(messageClass_); +} + +- (GPBDescriptor *)containingType { + NSValue *parentNameValue = + objc_getAssociatedObject(self, &kParentClassNameValueKey); + if (!parentNameValue) { + return nil; + } + const char *parentName = [parentNameValue pointerValue]; + Class parentClass = objc_getClass(parentName); + NSAssert(parentClass, @"Class %s not defined", parentName); + return [parentClass descriptor]; +} + +- (NSString *)fullName { + NSString *className = NSStringFromClass(self.messageClass); + GPBFileDescriptor *file = self.file; + NSString *objcPrefix = file.objcPrefix; + if (objcPrefix && ![className hasPrefix:objcPrefix]) { + NSAssert(0, + @"Class didn't have correct prefix? (%@ - %@)", + className, objcPrefix); + return nil; + } + GPBDescriptor *parent = self.containingType; + + NSString *name = nil; + if (parent) { + NSString *parentClassName = NSStringFromClass(parent.messageClass); + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); + if (suffix) { + if (![parentClassName hasSuffix:suffix]) { + NSAssert(0, + @"ParentMessage class didn't have correct suffix? (%@ - %@)", + className, suffix); + return nil; + } + parentClassName = + [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; + } + NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; + if (![className hasPrefix:parentPrefix]) { + NSAssert(0, + @"Class didn't have the correct parent name prefix? (%@ - %@)", + parentPrefix, className); + return nil; + } + name = [className substringFromIndex:parentPrefix.length]; + } else { + name = [className substringFromIndex:objcPrefix.length]; + } + + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); + if (suffix) { + if (![name hasSuffix:suffix]) { + NSAssert(0, + @"Message class didn't have correct suffix? (%@ - %@)", + name, suffix); + return nil; + } + name = [name substringToIndex:(name.length - suffix.length)]; + } + + NSString *prefix = (parent != nil ? parent.fullName : file.package); + NSString *result; + if (prefix.length > 0) { + result = [NSString stringWithFormat:@"%@.%@", prefix, name]; + } else { + result = name; + } + return result; +} + +- (id)copyWithZone:(NSZone *)zone { +#pragma unused(zone) + return [self retain]; +} + +- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { + for (GPBFieldDescriptor *descriptor in fields_) { + if (GPBFieldNumber(descriptor) == fieldNumber) { + return descriptor; + } + } + return nil; +} + +- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { + for (GPBFieldDescriptor *descriptor in fields_) { + if ([descriptor.name isEqual:name]) { + return descriptor; + } + } + return nil; +} + +- (GPBOneofDescriptor *)oneofWithName:(NSString *)name { + for (GPBOneofDescriptor *descriptor in oneofs_) { + if ([descriptor.name isEqual:name]) { + return descriptor; + } + } + return nil; +} + +@end + +@implementation GPBFileDescriptor { + NSString *package_; + NSString *objcPrefix_; + GPBFileSyntax syntax_; +} + +@synthesize package = package_; +@synthesize objcPrefix = objcPrefix_; +@synthesize syntax = syntax_; + +- (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax { + self = [super init]; + if (self) { + package_ = [package copy]; + objcPrefix_ = [objcPrefix copy]; + syntax_ = syntax; + } + return self; +} + +- (instancetype)initWithPackage:(NSString *)package + syntax:(GPBFileSyntax)syntax { + self = [super init]; + if (self) { + package_ = [package copy]; + syntax_ = syntax; + } + return self; +} + +- (void)dealloc { + [package_ release]; + [objcPrefix_ release]; + [super dealloc]; +} + +@end + +@implementation GPBOneofDescriptor + +@synthesize fields = fields_; + +- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { + self = [super init]; + if (self) { + name_ = name; + fields_ = [fields retain]; + for (GPBFieldDescriptor *fieldDesc in fields) { + fieldDesc->containingOneof_ = self; + } + + caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO); + } + return self; +} + +- (void)dealloc { + [fields_ release]; + [super dealloc]; +} + +- (NSString *)name { + return (NSString * _Nonnull)@(name_); +} + +- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { + for (GPBFieldDescriptor *descriptor in fields_) { + if (GPBFieldNumber(descriptor) == fieldNumber) { + return descriptor; + } + } + return nil; +} + +- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { + for (GPBFieldDescriptor *descriptor in fields_) { + if ([descriptor.name isEqual:name]) { + return descriptor; + } + } + return nil; +} + +@end + +uint32_t GPBFieldTag(GPBFieldDescriptor *self) { + GPBMessageFieldDescription *description = self->description_; + GPBWireFormat format; + if ((description->flags & GPBFieldMapKeyMask) != 0) { + // Maps are repeated messages on the wire. + format = GPBWireFormatForType(GPBDataTypeMessage, NO); + } else { + format = GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) != 0)); + } + return GPBWireFormatMakeTag(description->number, format); +} + +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { + GPBMessageFieldDescription *description = self->description_; + NSCAssert((description->flags & GPBFieldRepeated) != 0, + @"Only valid on repeated fields"); + GPBWireFormat format = + GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) == 0)); + return GPBWireFormatMakeTag(description->number, format); +} + +@implementation GPBFieldDescriptor { + GPBGenericValue defaultValue_; + + // Message ivars + Class msgClass_; + + // Enum ivars. + // If protos are generated with GenerateEnumDescriptors on then it will + // be a enumDescriptor, otherwise it will be a enumVerifier. + union { + GPBEnumDescriptor *enumDescriptor_; + GPBEnumValidationFunc enumVerifier_; + } enumHandling_; +} + +@synthesize msgClass = msgClass_; +@synthesize containingOneof = containingOneof_; + +- (instancetype)init { + // Throw an exception if people attempt to not use the designated initializer. + self = [super init]; + if (self != nil) { + [self doesNotRecognizeSelector:_cmd]; + self = nil; + } + return self; +} + +- (instancetype)initWithFieldDescription:(void *)description + includesDefault:(BOOL)includesDefault + syntax:(GPBFileSyntax)syntax { + if ((self = [super init])) { + GPBMessageFieldDescription *coreDesc; + if (includesDefault) { + coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core); + } else { + coreDesc = description; + } + description_ = coreDesc; + getSel_ = sel_getUid(coreDesc->name); + setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES); + + GPBDataType dataType = coreDesc->dataType; + BOOL isMessage = GPBDataTypeIsMessage(dataType); + BOOL isMapOrArray = GPBFieldIsMapOrArray(self); + + if (isMapOrArray) { + // map<>/repeated fields get a *Count property (inplace of a has*) to + // support checking if there are any entries without triggering + // autocreation. + hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); + } else { + // If there is a positive hasIndex, then: + // - All fields types for proto2 messages get has* selectors. + // - Only message fields for proto3 messages get has* selectors. + // Note: the positive check is to handle oneOfs, we can't check + // containingOneof_ because it isn't set until after initialization. + if ((coreDesc->hasIndex >= 0) && + (coreDesc->hasIndex != GPBNoHasBit) && + ((syntax != GPBFileSyntaxProto3) || isMessage)) { + hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); + setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); + } + } + + // Extra type specific data. + if (isMessage) { + const char *className = coreDesc->dataTypeSpecific.className; + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). + msgClass_ = objc_getClass(className); + NSAssert(msgClass_, @"Class %s not defined", className); + } else if (dataType == GPBDataTypeEnum) { + if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { + enumHandling_.enumDescriptor_ = + coreDesc->dataTypeSpecific.enumDescFunc(); + } else { + enumHandling_.enumVerifier_ = + coreDesc->dataTypeSpecific.enumVerifier; + } + } + + // Non map<>/repeated fields can have defaults in proto2 syntax. + if (!isMapOrArray && includesDefault) { + defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue; + if (dataType == GPBDataTypeBytes) { + // Data stored as a length prefixed (network byte order) c-string in + // descriptor structure. + const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; + if (bytes) { + uint32_t length; + memcpy(&length, bytes, sizeof(length)); + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } + } + } + return self; +} + +- (void)dealloc { + if (description_->dataType == GPBDataTypeBytes && + !(description_->flags & GPBFieldRepeated)) { + [defaultValue_.valueData release]; + } + [super dealloc]; +} + +- (GPBDataType)dataType { + return description_->dataType; +} + +- (BOOL)hasDefaultValue { + return (description_->flags & GPBFieldHasDefaultValue) != 0; +} + +- (uint32_t)number { + return description_->number; +} + +- (NSString *)name { + return (NSString * _Nonnull)@(description_->name); +} + +- (BOOL)isRequired { + return (description_->flags & GPBFieldRequired) != 0; +} + +- (BOOL)isOptional { + return (description_->flags & GPBFieldOptional) != 0; +} + +- (GPBFieldType)fieldType { + GPBFieldFlags flags = description_->flags; + if ((flags & GPBFieldRepeated) != 0) { + return GPBFieldTypeRepeated; + } else if ((flags & GPBFieldMapKeyMask) != 0) { + return GPBFieldTypeMap; + } else { + return GPBFieldTypeSingle; + } +} + +- (GPBDataType)mapKeyDataType { + switch (description_->flags & GPBFieldMapKeyMask) { + case GPBFieldMapKeyInt32: + return GPBDataTypeInt32; + case GPBFieldMapKeyInt64: + return GPBDataTypeInt64; + case GPBFieldMapKeyUInt32: + return GPBDataTypeUInt32; + case GPBFieldMapKeyUInt64: + return GPBDataTypeUInt64; + case GPBFieldMapKeySInt32: + return GPBDataTypeSInt32; + case GPBFieldMapKeySInt64: + return GPBDataTypeSInt64; + case GPBFieldMapKeyFixed32: + return GPBDataTypeFixed32; + case GPBFieldMapKeyFixed64: + return GPBDataTypeFixed64; + case GPBFieldMapKeySFixed32: + return GPBDataTypeSFixed32; + case GPBFieldMapKeySFixed64: + return GPBDataTypeSFixed64; + case GPBFieldMapKeyBool: + return GPBDataTypeBool; + case GPBFieldMapKeyString: + return GPBDataTypeString; + + default: + NSAssert(0, @"Not a map type"); + return GPBDataTypeInt32; // For lack of anything better. + } +} + +- (BOOL)isPackable { + return (description_->flags & GPBFieldPacked) != 0; +} + +- (BOOL)isValidEnumValue:(int32_t)value { + NSAssert(description_->dataType == GPBDataTypeEnum, + @"Field Must be of type GPBDataTypeEnum"); + if (description_->flags & GPBFieldHasEnumDescriptor) { + return enumHandling_.enumDescriptor_.enumVerifier(value); + } else { + return enumHandling_.enumVerifier_(value); + } +} + +- (GPBEnumDescriptor *)enumDescriptor { + if (description_->flags & GPBFieldHasEnumDescriptor) { + return enumHandling_.enumDescriptor_; + } else { + return nil; + } +} + +- (GPBGenericValue)defaultValue { + // Depends on the fact that defaultValue_ is initialized either to "0/nil" or + // to an actual defaultValue in our initializer. + GPBGenericValue value = defaultValue_; + + if (!(description_->flags & GPBFieldRepeated)) { + // We special handle data and strings. If they are nil, we replace them + // with empty string/empty data. + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes && value.valueData == nil) { + value.valueData = GPBEmptyNSData(); + } else if (type == GPBDataTypeString && value.valueString == nil) { + value.valueString = @""; + } + } + return value; +} + +- (NSString *)textFormatName { + if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) { + NSValue *extraInfoValue = + objc_getAssociatedObject(self, &kTextFormatExtraValueKey); + // Support can be left out at generation time. + if (!extraInfoValue) { + return nil; + } + const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue]; + return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self), + self.name); + } + + // The logic here has to match SetCommonFieldVariables() from + // objectivec_field.cc in the proto compiler. + NSString *name = self.name; + NSUInteger len = [name length]; + + // Remove the "_p" added to reserved names. + if ([name hasSuffix:@"_p"]) { + name = [name substringToIndex:(len - 2)]; + len = [name length]; + } + + // Remove "Array" from the end for repeated fields. + if (((description_->flags & GPBFieldRepeated) != 0) && + [name hasSuffix:@"Array"]) { + name = [name substringToIndex:(len - 5)]; + len = [name length]; + } + + // Groups vs. other fields. + if (description_->dataType == GPBDataTypeGroup) { + // Just capitalize the first letter. + unichar firstChar = [name characterAtIndex:0]; + if (firstChar >= 'a' && firstChar <= 'z') { + NSString *firstCharString = + [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')]; + NSString *result = + [name stringByReplacingCharactersInRange:NSMakeRange(0, 1) + withString:firstCharString]; + return result; + } + return name; + + } else { + // Undo the CamelCase. + NSMutableString *result = [NSMutableString stringWithCapacity:len]; + for (uint32_t i = 0; i < len; i++) { + unichar c = [name characterAtIndex:i]; + if (c >= 'A' && c <= 'Z') { + if (i > 0) { + [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')]; + } else { + [result appendFormat:@"%C", c]; + } + } else { + [result appendFormat:@"%C", c]; + } + } + return result; + } +} + +@end + +@implementation GPBEnumDescriptor { + NSString *name_; + // valueNames_ is a single c string with all of the value names appended + // together, each null terminated. -calcValueNameOffsets fills in + // nameOffsets_ with the offsets to allow quicker access to the individual + // names. + const char *valueNames_; + const int32_t *values_; + GPBEnumValidationFunc enumVerifier_; + const uint8_t *extraTextFormatInfo_; + uint32_t *nameOffsets_; + uint32_t valueCount_; +} + +@synthesize name = name_; +@synthesize enumVerifier = enumVerifier_; + ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier { + GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name + valueNames:valueNames + values:values + count:valueCount + enumVerifier:enumVerifier]; + return descriptor; +} + ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier + extraTextFormatInfo:(const char *)extraTextFormatInfo { + // Call the common case. + GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name + valueNames:valueNames + values:values + count:valueCount + enumVerifier:enumVerifier]; + // Set the extra info. + descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo; + return descriptor; +} + +- (instancetype)initWithName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier { + if ((self = [super init])) { + name_ = [name copy]; + valueNames_ = valueNames; + values_ = values; + valueCount_ = valueCount; + enumVerifier_ = enumVerifier; + } + return self; +} + +- (void)dealloc { + [name_ release]; + if (nameOffsets_) free(nameOffsets_); + [super dealloc]; +} + +- (void)calcValueNameOffsets { + @synchronized(self) { + if (nameOffsets_ != NULL) { + return; + } + uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t)); + if (!offsets) return; + const char *scan = valueNames_; + for (uint32_t i = 0; i < valueCount_; ++i) { + offsets[i] = (uint32_t)(scan - valueNames_); + while (*scan != '\0') ++scan; + ++scan; // Step over the null. + } + nameOffsets_ = offsets; + } +} + +- (NSString *)enumNameForValue:(int32_t)number { + for (uint32_t i = 0; i < valueCount_; ++i) { + if (values_[i] == number) { + return [self getEnumNameForIndex:i]; + } + } + return nil; +} + +- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { + // Must have the prefix. + NSUInteger prefixLen = name_.length + 1; + if ((name.length <= prefixLen) || ![name hasPrefix:name_] || + ([name characterAtIndex:prefixLen - 1] != '_')) { + return NO; + } + + // Skip over the prefix. + const char *nameAsCStr = [name UTF8String]; + nameAsCStr += prefixLen; + + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return NO; + + // Find it. + for (uint32_t i = 0; i < valueCount_; ++i) { + const char *valueName = valueNames_ + nameOffsets_[i]; + if (strcmp(nameAsCStr, valueName) == 0) { + if (outValue) { + *outValue = values_[i]; + } + return YES; + } + } + return NO; +} + +- (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return NO; + + for (uint32_t i = 0; i < valueCount_; ++i) { + NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i]; + if ([valueTextFormatName isEqual:textFormatName]) { + if (outValue) { + *outValue = values_[i]; + } + return YES; + } + } + return NO; +} + +- (NSString *)textFormatNameForValue:(int32_t)number { + // Find the EnumValue descriptor and its index. + BOOL foundIt = NO; + uint32_t valueDescriptorIndex; + for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; + ++valueDescriptorIndex) { + if (values_[valueDescriptorIndex] == number) { + foundIt = YES; + break; + } + } + + if (!foundIt) { + return nil; + } + return [self getEnumTextFormatNameForIndex:valueDescriptorIndex]; +} + +- (uint32_t)enumNameCount { + return valueCount_; +} + +- (NSString *)getEnumNameForIndex:(uint32_t)index { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return nil; + + if (index >= valueCount_) { + return nil; + } + const char *valueName = valueNames_ + nameOffsets_[index]; + NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; + return fullName; +} + +- (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return nil; + + if (index >= valueCount_) { + return nil; + } + NSString *result = nil; + // Naming adds an underscore between enum name and value name, skip that also. + const char *valueName = valueNames_ + nameOffsets_[index]; + NSString *shortName = @(valueName); + + // See if it is in the map of special format handling. + if (extraTextFormatInfo_) { + result = GPBDecodeTextFormatName(extraTextFormatInfo_, + (int32_t)index, shortName); + } + // Logic here needs to match what objectivec_enum.cc does in the proto + // compiler. + if (result == nil) { + NSUInteger len = [shortName length]; + NSMutableString *worker = [NSMutableString stringWithCapacity:len]; + for (NSUInteger i = 0; i < len; i++) { + unichar c = [shortName characterAtIndex:i]; + if (i > 0 && c >= 'A' && c <= 'Z') { + [worker appendString:@"_"]; + } + [worker appendFormat:@"%c", toupper((char)c)]; + } + result = worker; + } + return result; +} + +@end + +@implementation GPBExtensionDescriptor { + GPBGenericValue defaultValue_; +} + +@synthesize containingMessageClass = containingMessageClass_; + +- (instancetype)initWithExtensionDescription: + (GPBExtensionDescription *)description { + if ((self = [super init])) { + description_ = description; + +#if defined(DEBUG) && DEBUG + const char *className = description->messageOrGroupClassName; + if (className) { + NSAssert(objc_lookUpClass(className) != Nil, + @"Class %s not defined", className); + } +#endif + + if (description->extendedClass) { + Class containingClass = objc_lookUpClass(description->extendedClass); + NSAssert(containingClass, @"Class %s not defined", + description->extendedClass); + containingMessageClass_ = containingClass; + } + + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes) { + // Data stored as a length prefixed c-string in descriptor records. + const uint8_t *bytes = + (const uint8_t *)description->defaultValue.valueData; + if (bytes) { + uint32_t length; + memcpy(&length, bytes, sizeof(length)); + // The length is stored in network byte order. + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) { + // The default is looked up in -defaultValue instead since extensions + // aren't common, we avoid the hit startup hit and it avoid initialization + // order issues. + } else { + defaultValue_ = description->defaultValue; + } + } + return self; +} + +- (void)dealloc { + if ((description_->dataType == GPBDataTypeBytes) && + !GPBExtensionIsRepeated(description_)) { + [defaultValue_.valueData release]; + } + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { +#pragma unused(zone) + // Immutable. + return [self retain]; +} + +- (NSString *)singletonName { + return (NSString * _Nonnull)@(description_->singletonName); +} + +- (const char *)singletonNameC { + return description_->singletonName; +} + +- (uint32_t)fieldNumber { + return description_->fieldNumber; +} + +- (GPBDataType)dataType { + return description_->dataType; +} + +- (GPBWireFormat)wireType { + return GPBWireFormatForType(description_->dataType, + GPBExtensionIsPacked(description_)); +} + +- (GPBWireFormat)alternateWireType { + NSAssert(GPBExtensionIsRepeated(description_), + @"Only valid on repeated extensions"); + return GPBWireFormatForType(description_->dataType, + !GPBExtensionIsPacked(description_)); +} + +- (BOOL)isRepeated { + return GPBExtensionIsRepeated(description_); +} + +- (BOOL)isPackable { + return GPBExtensionIsPacked(description_); +} + +- (Class)msgClass { + return objc_getClass(description_->messageOrGroupClassName); +} + +- (GPBEnumDescriptor *)enumDescriptor { + if (description_->dataType == GPBDataTypeEnum) { + GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); + return enumDescriptor; + } + return nil; +} + +- (id)defaultValue { + if (GPBExtensionIsRepeated(description_)) { + return nil; + } + + switch (description_->dataType) { + case GPBDataTypeBool: + return @(defaultValue_.valueBool); + case GPBDataTypeFloat: + return @(defaultValue_.valueFloat); + case GPBDataTypeDouble: + return @(defaultValue_.valueDouble); + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeSFixed32: + return @(defaultValue_.valueInt32); + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeSFixed64: + return @(defaultValue_.valueInt64); + case GPBDataTypeUInt32: + case GPBDataTypeFixed32: + return @(defaultValue_.valueUInt32); + case GPBDataTypeUInt64: + case GPBDataTypeFixed64: + return @(defaultValue_.valueUInt64); + case GPBDataTypeBytes: + // Like message fields, the default is zero length data. + return (defaultValue_.valueData ? defaultValue_.valueData + : GPBEmptyNSData()); + case GPBDataTypeString: + // Like message fields, the default is zero length string. + return (defaultValue_.valueString ? defaultValue_.valueString : @""); + case GPBDataTypeGroup: + case GPBDataTypeMessage: + return nil; + } +} + +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other { + int32_t selfNumber = description_->fieldNumber; + int32_t otherNumber = other->description_->fieldNumber; + if (selfNumber < otherNumber) { + return NSOrderedAscending; + } else if (selfNumber == otherNumber) { + return NSOrderedSame; + } else { + return NSOrderedDescending; + } +} + +@end + +#pragma clang diagnostic pop diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor_PackagePrivate.h new file mode 100644 index 0000000..452b3f8 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDescriptor_PackagePrivate.h @@ -0,0 +1,325 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is private to the ProtobolBuffers library and must NOT be +// included by any sources outside this library. The contents of this file are +// subject to change at any time without notice. + +#import "GPBDescriptor.h" +#import "GPBWireFormat.h" + +// Describes attributes of the field. +typedef NS_OPTIONS(uint16_t, GPBFieldFlags) { + GPBFieldNone = 0, + // These map to standard protobuf concepts. + GPBFieldRequired = 1 << 0, + GPBFieldRepeated = 1 << 1, + GPBFieldPacked = 1 << 2, + GPBFieldOptional = 1 << 3, + GPBFieldHasDefaultValue = 1 << 4, + + // Indicates the field needs custom handling for the TextFormat name, if not + // set, the name can be derived from the ObjC name. + GPBFieldTextFormatNameCustom = 1 << 6, + // Indicates the field has an enum descriptor. + GPBFieldHasEnumDescriptor = 1 << 7, + + // These are not standard protobuf concepts, they are specific to the + // Objective C runtime. + + // These bits are used to mark the field as a map and what the key + // type is. + GPBFieldMapKeyMask = 0xF << 8, + GPBFieldMapKeyInt32 = 1 << 8, + GPBFieldMapKeyInt64 = 2 << 8, + GPBFieldMapKeyUInt32 = 3 << 8, + GPBFieldMapKeyUInt64 = 4 << 8, + GPBFieldMapKeySInt32 = 5 << 8, + GPBFieldMapKeySInt64 = 6 << 8, + GPBFieldMapKeyFixed32 = 7 << 8, + GPBFieldMapKeyFixed64 = 8 << 8, + GPBFieldMapKeySFixed32 = 9 << 8, + GPBFieldMapKeySFixed64 = 10 << 8, + GPBFieldMapKeyBool = 11 << 8, + GPBFieldMapKeyString = 12 << 8, +}; + +// NOTE: The structures defined here have their members ordered to minimize +// their size. This directly impacts the size of apps since these exist per +// field/extension. + +// Describes a single field in a protobuf as it is represented as an ivar. +typedef struct GPBMessageFieldDescription { + // Name of ivar. + const char *name; + union { + const char *className; // Name for message class. + // For enums only: If EnumDescriptors are compiled in, it will be that, + // otherwise it will be the verifier. + GPBEnumDescriptorFunc enumDescFunc; + GPBEnumValidationFunc enumVerifier; + } dataTypeSpecific; + // The field number for the ivar. + uint32_t number; + // The index (in bits) into _has_storage_. + // >= 0: the bit to use for a value being set. + // = GPBNoHasBit(INT32_MAX): no storage used. + // < 0: in a oneOf, use a full int32 to record the field active. + int32_t hasIndex; + // Offset of the variable into it's structure struct. + uint32_t offset; + // Field flags. Use accessor functions below. + GPBFieldFlags flags; + // Data type of the ivar. + GPBDataType dataType; +} GPBMessageFieldDescription; + +// Fields in messages defined in a 'proto2' syntax file can provide a default +// value. This struct provides the default along with the field info. +typedef struct GPBMessageFieldDescriptionWithDefault { + // Default value for the ivar. + GPBGenericValue defaultValue; + + GPBMessageFieldDescription core; +} GPBMessageFieldDescriptionWithDefault; + +// Describes attributes of the extension. +typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) { + GPBExtensionNone = 0, + // These map to standard protobuf concepts. + GPBExtensionRepeated = 1 << 0, + GPBExtensionPacked = 1 << 1, + GPBExtensionSetWireFormat = 1 << 2, +}; + +// An extension +typedef struct GPBExtensionDescription { + GPBGenericValue defaultValue; + const char *singletonName; + const char *extendedClass; + const char *messageOrGroupClassName; + GPBEnumDescriptorFunc enumDescriptorFunc; + int32_t fieldNumber; + GPBDataType dataType; + GPBExtensionOptions options; +} GPBExtensionDescription; + +typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { + GPBDescriptorInitializationFlag_None = 0, + GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0, + GPBDescriptorInitializationFlag_WireFormat = 1 << 1, +}; + +@interface GPBDescriptor () { + @package + NSArray *fields_; + NSArray *oneofs_; + uint32_t storageSize_; +} + +// fieldDescriptions have to be long lived, they are held as raw pointers. ++ (instancetype) + allocDescriptorForClass:(Class)messageClass + rootClass:(Class)rootClass + file:(GPBFileDescriptor *)file + fields:(void *)fieldDescriptions + fieldCount:(uint32_t)fieldCount + storageSize:(uint32_t)storageSize + flags:(GPBDescriptorInitializationFlags)flags; + +- (instancetype)initWithClass:(Class)messageClass + file:(GPBFileDescriptor *)file + fields:(NSArray *)fields + storageSize:(uint32_t)storage + wireFormat:(BOOL)wireFormat; + +// Called right after init to provide extra information to avoid init having +// an explosion of args. These pointers are recorded, so they are expected +// to live for the lifetime of the app. +- (void)setupOneofs:(const char **)oneofNames + count:(uint32_t)count + firstHasIndex:(int32_t)firstHasIndex; +- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; +- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; +- (void)setupContainingMessageClassName:(const char *)msgClassName; +- (void)setupMessageClassNameSuffix:(NSString *)suffix; + +@end + +@interface GPBFileDescriptor () +- (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax; +- (instancetype)initWithPackage:(NSString *)package + syntax:(GPBFileSyntax)syntax; +@end + +@interface GPBOneofDescriptor () { + @package + const char *name_; + NSArray *fields_; + SEL caseSel_; +} +// name must be long lived. +- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields; +@end + +@interface GPBFieldDescriptor () { + @package + GPBMessageFieldDescription *description_; + GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_; + + SEL getSel_; + SEL setSel_; + SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise. + SEL setHasSel_; +} + +// Single initializer +// description has to be long lived, it is held as a raw pointer. +- (instancetype)initWithFieldDescription:(void *)description + includesDefault:(BOOL)includesDefault + syntax:(GPBFileSyntax)syntax; +@end + +@interface GPBEnumDescriptor () +// valueNames, values and extraTextFormatInfo have to be long lived, they are +// held as raw pointers. ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier; ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier + extraTextFormatInfo:(const char *)extraTextFormatInfo; + +- (instancetype)initWithName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier; +@end + +@interface GPBExtensionDescriptor () { + @package + GPBExtensionDescription *description_; +} +@property(nonatomic, readonly) GPBWireFormat wireType; + +// For repeated extensions, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the extension was marked packed +// it would be the wire type for unpacked; if the extension was marked unpacked, +// it would be the wire type for packed. +@property(nonatomic, readonly) GPBWireFormat alternateWireType; + +// description has to be long lived, it is held as a raw pointer. +- (instancetype)initWithExtensionDescription: + (GPBExtensionDescription *)description; +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; +@end + +CF_EXTERN_C_BEGIN + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) { + return (field->description_->flags & + (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0; +} + +GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) { + return field->description_->dataType; +} + +GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) { + return field->description_->hasIndex; +} + +GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) { + return field->description_->number; +} + +#pragma clang diagnostic pop + +uint32_t GPBFieldTag(GPBFieldDescriptor *self); + +// For repeated fields, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the field was marked packed it +// would be the wire type for unpacked; if the field was marked unpacked, it +// would be the wire type for packed. +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self); + +GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) { + return syntax == GPBFileSyntaxProto3; +} + +GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) { + return (description->options & GPBExtensionRepeated) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) { + return (description->options & GPBExtensionPacked) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) { + return (description->options & GPBExtensionSetWireFormat) != 0; +} + +// Helper for compile time assets. +#ifndef GPBInternalCompileAssert + #if __has_feature(c_static_assert) || __has_extension(c_static_assert) + #define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg) + #else + // Pre-Xcode 7 support. + #define GPBInternalCompileAssertSymbolInner(line, msg) GPBInternalCompileAssert ## line ## __ ## msg + #define GPBInternalCompileAssertSymbol(line, msg) GPBInternalCompileAssertSymbolInner(line, msg) + #define GPBInternalCompileAssert(test, msg) \ + typedef char GPBInternalCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] + #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert) +#endif // GPBInternalCompileAssert + +// Sanity check that there isn't padding between the field description +// structures with and without a default. +GPBInternalCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) == + (sizeof(GPBGenericValue) + + sizeof(GPBMessageFieldDescription)), + DescriptionsWithDefault_different_size_than_expected); + +CF_EXTERN_C_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary.h new file mode 100644 index 0000000..d00b5b3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary.h @@ -0,0 +1,5770 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" + +// Note on naming: for the classes holding numeric values, a more natural +// naming of the method might be things like "-valueForKey:", +// "-setValue:forKey:"; etc. But those selectors are also defined by Key Value +// Coding (KVC) as categories on NSObject. So "overloading" the selectors with +// other meanings can cause warnings (based on compiler settings), but more +// importantly, some of those selector get called as KVC breaks up keypaths. +// So if those selectors are used, using KVC will compile cleanly, but could +// crash as it invokes those selectors with the wrong types of arguments. + +NS_ASSUME_NONNULL_BEGIN + +//%PDDM-EXPAND DECLARE_DICTIONARIES() +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt32 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(uint32_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(int32_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(uint64_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(int64_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolUInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolUInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolBoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolFloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolDoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolEnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(BOOL)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringUInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringUInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringBoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringFloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringDoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringEnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(NSString *)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +//%PDDM-EXPAND-END DECLARE_DICTIONARIES() + +NS_ASSUME_NONNULL_END + +//%PDDM-DEFINE DECLARE_DICTIONARIES() +//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt32, uint32_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int32, int32_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt64, uint64_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int64, int64_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(Bool, BOOL) +//%DICTIONARY_POD_INTERFACES_FOR_KEY(String, NSString, *, OBJECT) +//%PDDM-DEFINE DICTIONARY_INTERFACES_FOR_POD_KEY(KEY_NAME, KEY_TYPE) +//%DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, , POD) +//%DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, Object, ObjectType) +//%PDDM-DEFINE DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt32, uint32_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int32, int32_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt64, uint64_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int64, int64_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Bool, BOOL) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Float, float) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Double, double) +//%DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Enum, int32_t) +//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, POD, VALUE_NAME, value) +//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, , POD, VALUE_NAME, VALUE_TYPE, OBJECT, Object, object) +//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE, VNAME) +//%/** +//% * Gets the value for the given key. +//% * +//% * @param value Pointer into which the value will be set, if found. +//% * @param key Key under which the value is stored, if present. +//% * +//% * @return YES if the key was found and the value was copied, NO otherwise. +//% **/ +//%- (BOOL)get##VNAME##:(nullable VALUE_TYPE *)value forKey:(KEY_TYPE)key; +//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_TYPE, VNAME) +//%/** +//% * Fetches the object stored under the given key. +//% * +//% * @param key Key under which the value is stored, if present. +//% * +//% * @return The object if found, nil otherwise. +//% **/ +//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key; +//%PDDM-DEFINE VALUE_FOR_KEY_Enum(KEY_TYPE, VALUE_TYPE, VNAME) +//%VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE, VNAME) +//%PDDM-DEFINE ARRAY_ARG_MODIFIERPOD() +// Nothing +//%PDDM-DEFINE ARRAY_ARG_MODIFIEREnum() +// Nothing +//%PDDM-DEFINE ARRAY_ARG_MODIFIEROBJECT() +//%__nonnull GPB_UNSAFE_UNRETAINED ## +//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE) +//%GPB##KEY_NAME##VALUE_NAME##Dictionary +//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE) +//%GPB##KEY_NAME##VALUE_NAME##Dictionary +//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE) +//%GPB##KEY_NAME##VALUE_NAME##Dictionary<__covariant VALUE_TYPE> +//%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%/** +//% * Class used for map fields of <##KEY_TYPE##, ##VALUE_TYPE##> +//% * values. This performs better than boxing into NSNumbers in NSDictionaries. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) : NSObject +//% +//%/** Number of entries stored in this dictionary. */ +//%@property(nonatomic, readonly) NSUInteger count; +//% +//%/** +//% * Initializes this dictionary, copying the given values and keys. +//% * +//% * @param ##VNAME_VAR##s The values to be placed in this dictionary. +//% * @param keys ##VNAME_VAR$S## The keys under which to store the values. +//% * @param count ##VNAME_VAR$S## The number of elements to copy into the dictionary. +//% * +//% * @return A newly initialized dictionary with a copy of the values and keys. +//% **/ +//%- (instancetype)initWith##VNAME##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[__nullable])##VNAME_VAR##s +//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[__nullable])keys +//% ##VNAME$S## count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes this dictionary, copying the entries from the given dictionary. +//% * +//% * @param dictionary Dictionary containing the entries to add to this dictionary. +//% * +//% * @return A newly initialized dictionary with the entries of the given dictionary. +//% **/ +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary; +//% +//%/** +//% * Initializes this dictionary with the requested capacity. +//% * +//% * @param numItems Number of items needed for this dictionary. +//% * +//% * @return A newly initialized dictionary with the requested capacity. +//% **/ +//%- (instancetype)initWithCapacity:(NSUInteger)numItems; +//% +//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//% +//%/** +//% * Adds the keys and values from another dictionary. +//% * +//% * @param otherDictionary Dictionary containing entries to be added to this +//% * dictionary. +//% **/ +//%- (void)addEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary; +//% +//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, Enum) +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%/** +//% * Class used for map fields of <##KEY_TYPE##, ##VALUE_TYPE##> +//% * values. This performs better than boxing into NSNumbers in NSDictionaries. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject +//% +//%/** Number of entries stored in this dictionary. */ +//%@property(nonatomic, readonly) NSUInteger count; +//%/** The validation function to check if the enums are valid. */ +//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; +//% +//%/** +//% * Initializes a dictionary with the given validation function. +//% * +//% * @param func The enum validation function for the dictionary. +//% * +//% * @return A newly initialized dictionary. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//% +//%/** +//% * Initializes a dictionary with the entries given. +//% * +//% * @param func The enum validation function for the dictionary. +//% * @param values The raw enum values values to be placed in the dictionary. +//% * @param keys The keys under which to store the values. +//% * @param count The number of entries to store in the dictionary. +//% * +//% * @return A newly initialized dictionary with the keys and values in it. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[__nullable])values +//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[__nullable])keys +//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes a dictionary with the entries from the given. +//% * dictionary. +//% * +//% * @param dictionary Dictionary containing the entries to add to the dictionary. +//% * +//% * @return A newly initialized dictionary with the entries from the given +//% * dictionary in it. +//% **/ +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary; +//% +//%/** +//% * Initializes a dictionary with the given capacity. +//% * +//% * @param func The enum validation function for the dictionary. +//% * @param numItems Capacity needed for the dictionary. +//% * +//% * @return A newly initialized dictionary with the given capacity. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% capacity:(NSUInteger)numItems; +//% +//%// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +//%// is not a valid enumerator as defined by validationFunc. If the actual value is +//%// desired, use "raw" version of the method. +//% +//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, Enum, value) +//% +//%/** +//% * Gets the raw enum value for the given key. +//% * +//% * @note This method bypass the validationFunc to enable the access of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param rawValue Pointer into which the value will be set, if found. +//% * @param key Key under which the value is stored, if present. +//% * +//% * @return YES if the key was found and the value was copied, NO otherwise. +//% **/ +//%- (BOOL)getRawValue:(nullable VALUE_TYPE *)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key; +//% +//%/** +//% * Enumerates the keys and values on this dictionary with the given block. +//% * +//% * @note This method bypass the validationFunc to enable the access of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param block The block to enumerate with. +//% * **key**: The key for the current entry. +//% * **rawValue**: The value for the current entry +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateKeysAndRawValuesUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block; +//% +//%/** +//% * Adds the keys and raw enum values from another dictionary. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param otherDictionary Dictionary containing entries to be added to this +//% * dictionary. +//% **/ +//%- (void)addRawEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary; +//% +//%// If value is not a valid enumerator as defined by validationFunc, these +//%// methods will assert in debug, and will log in release and assign the value +//%// to the default value. Use the rawValue methods below to assign non enumerator +//%// values. +//% +//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, Enum, value) +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_TYPE, VNAME) +//% +//%/** +//% * Enumerates the keys and values on this dictionary with the given block. +//% * +//% * @param block The block to enumerate with. +//% * **key**: ##VNAME_VAR$S## The key for the current entry. +//% * **VNAME_VAR**: The value for the current entry +//% * **stop**: ##VNAME_VAR$S## A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateKeysAnd##VNAME##sUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block; + +//%PDDM-DEFINE DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//%/** +//% * Sets the value for the given key. +//% * +//% * @param ##VNAME_VAR The value to set. +//% * @param key ##VNAME_VAR$S## The key under which to store the value. +//% **/ +//%- (void)set##VNAME##:(VALUE_TYPE)##VNAME_VAR forKey:(KEY_TYPE##KisP$S##KisP)key; +//%DICTIONARY_EXTRA_MUTABLE_METHODS_##VHELPER(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +//%/** +//% * Removes the entry for the given key. +//% * +//% * @param aKey Key to be removed from this dictionary. +//% **/ +//%- (void)remove##VNAME##ForKey:(KEY_TYPE##KisP$S##KisP)aKey; +//% +//%/** +//% * Removes all entries in this dictionary. +//% **/ +//%- (void)removeAll; + +//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_POD(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +// Empty +//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_OBJECT(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +// Empty +//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_Enum(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +//% +//%/** +//% * Sets the raw enum value for the given key. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param rawValue The raw enum value to set. +//% * @param key The key under which to store the raw enum value. +//% **/ +//%- (void)setRawValue:(VALUE_TYPE)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key; +//% diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary.m new file mode 100644 index 0000000..1bb24be --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary.m @@ -0,0 +1,12120 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBDictionary_PackagePrivate.h" + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +// ------------------------------ NOTE ------------------------------ +// At the moment, this is all using NSNumbers in NSDictionaries under +// the hood, but it is all hidden so we can come back and optimize +// with direct CFDictionary usage later. The reason that wasn't +// done yet is needing to support 32bit iOS builds. Otherwise +// it would be pretty simple to store all this data in CFDictionaries +// directly. +// ------------------------------------------------------------------ + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +// Used to include code only visible to specific versions of the static +// analyzer. Useful for wrapping code that only exists to silence the analyzer. +// Determine the values you want to use for BEGIN_APPLE_BUILD_VERSION, +// END_APPLE_BUILD_VERSION using: +// xcrun clang -dM -E -x c /dev/null | grep __apple_build_version__ +// Example usage: +// #if GPB_STATIC_ANALYZER_ONLY(5621, 5623) ... #endif +#define GPB_STATIC_ANALYZER_ONLY(BEGIN_APPLE_BUILD_VERSION, END_APPLE_BUILD_VERSION) \ + (defined(__clang_analyzer__) && \ + (__apple_build_version__ >= BEGIN_APPLE_BUILD_VERSION && \ + __apple_build_version__ <= END_APPLE_BUILD_VERSION)) + +enum { + kMapKeyFieldNumber = 1, + kMapValueFieldNumber = 2, +}; + +static BOOL DictDefault_IsValidValue(int32_t value) { + // Anything but the bad value marker is allowed. + return (value != kGPBUnrecognizedEnumeratorValue); +} + +//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% return 0; +//% } +//%} +//% +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% } +//%} +//% +//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2, GPBDATATYPE_NAME3) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% return GPBCompute##GPBDATATYPE_NAME3##Size(fieldNum, value); +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% return 0; +//% } +//%} +//% +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% [stream write##GPBDATATYPE_NAME3##:fieldNum value:value]; +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% } +//%} +//% +//%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. +//% return GPBCompute##VALUE_NAME##Size(fieldNum, value); +//%} +//% +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. +//% [stream write##VALUE_NAME##:fieldNum value:value]; +//%} +//% +//%PDDM-DEFINE SERIALIZE_SUPPORT_HELPERS() +//%SERIALIZE_SUPPORT_3_TYPE(Int32, int32_t, Int32, SInt32, SFixed32) +//%SERIALIZE_SUPPORT_2_TYPE(UInt32, uint32_t, UInt32, Fixed32) +//%SERIALIZE_SUPPORT_3_TYPE(Int64, int64_t, Int64, SInt64, SFixed64) +//%SERIALIZE_SUPPORT_2_TYPE(UInt64, uint64_t, UInt64, Fixed64) +//%SIMPLE_SERIALIZE_SUPPORT(Bool, BOOL, ) +//%SIMPLE_SERIALIZE_SUPPORT(Enum, int32_t, ) +//%SIMPLE_SERIALIZE_SUPPORT(Float, float, ) +//%SIMPLE_SERIALIZE_SUPPORT(Double, double, ) +//%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *) +//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes) +//%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS() +// This block of code is generated, do not edit it directly. + +static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { + return GPBComputeInt32Size(fieldNum, value); + } else if (dataType == GPBDataTypeSInt32) { + return GPBComputeSInt32Size(fieldNum, value); + } else if (dataType == GPBDataTypeSFixed32) { + return GPBComputeSFixed32Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { + [stream writeInt32:fieldNum value:value]; + } else if (dataType == GPBDataTypeSInt32) { + [stream writeSInt32:fieldNum value:value]; + } else if (dataType == GPBDataTypeSFixed32) { + [stream writeSFixed32:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { + return GPBComputeUInt32Size(fieldNum, value); + } else if (dataType == GPBDataTypeFixed32) { + return GPBComputeFixed32Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { + [stream writeUInt32:fieldNum value:value]; + } else if (dataType == GPBDataTypeFixed32) { + [stream writeFixed32:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { + return GPBComputeInt64Size(fieldNum, value); + } else if (dataType == GPBDataTypeSInt64) { + return GPBComputeSInt64Size(fieldNum, value); + } else if (dataType == GPBDataTypeSFixed64) { + return GPBComputeSFixed64Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { + [stream writeInt64:fieldNum value:value]; + } else if (dataType == GPBDataTypeSInt64) { + [stream writeSInt64:fieldNum value:value]; + } else if (dataType == GPBDataTypeSFixed64) { + [stream writeSFixed64:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { + return GPBComputeUInt64Size(fieldNum, value); + } else if (dataType == GPBDataTypeFixed64) { + return GPBComputeFixed64Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { + [stream writeUInt64:fieldNum value:value]; + } else if (dataType == GPBDataTypeFixed64) { + [stream writeFixed64:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeBoolSize(fieldNum, value); +} + +static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeBool:fieldNum value:value]; +} + +static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeEnumSize(fieldNum, value); +} + +static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeEnum:fieldNum value:value]; +} + +static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeFloatSize(fieldNum, value); +} + +static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeFloat:fieldNum value:value]; +} + +static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeDoubleSize(fieldNum, value); +} + +static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeDouble:fieldNum value:value]; +} + +static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeStringSize(fieldNum, value); +} + +static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeString:fieldNum value:value]; +} + +static size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { + return GPBComputeMessageSize(fieldNum, value); + } else if (dataType == GPBDataTypeString) { + return GPBComputeStringSize(fieldNum, value); + } else if (dataType == GPBDataTypeBytes) { + return GPBComputeBytesSize(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { + [stream writeMessage:fieldNum value:value]; + } else if (dataType == GPBDataTypeString) { + [stream writeString:fieldNum value:value]; + } else if (dataType == GPBDataTypeBytes) { + [stream writeBytes:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +//%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS() + +size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { + GPBDataType mapValueType = GPBGetFieldDataType(field); + size_t result = 0; + NSString *key; + NSEnumerator *keys = [dict keyEnumerator]; + while ((key = [keys nextObject])) { + id obj = dict[key]; + size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key); + msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * dict.count; + return result; +} + +void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream, + NSDictionary *dict, + GPBFieldDescriptor *field) { + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + GPBDataType mapValueType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSString *key; + NSEnumerator *keys = [dict keyEnumerator]; + while ((key = [keys nextObject])) { + id obj = dict[key]; + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key); + msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType); + + // Write the size and fields. + [outputStream writeInt32NoTag:(int32_t)msgSize]; + [outputStream writeString:kMapKeyFieldNumber value:key]; + WriteDictObjectField(outputStream, obj, kMapValueFieldNumber, mapValueType); + } +} + +BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type"); + #pragma unused(field) // For when asserts are off in release. + GPBMessage *msg; + NSEnumerator *objects = [dict objectEnumerator]; + while ((msg = [objects nextObject])) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +// Note: if the type is an object, it the retain pass back to the caller. +static void ReadValue(GPBCodedInputStream *stream, + GPBGenericValue *valueToFill, + GPBDataType type, + GPBExtensionRegistry *registry, + GPBFieldDescriptor *field) { + switch (type) { + case GPBDataTypeBool: + valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_); + break; + case GPBDataTypeFixed32: + valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_); + break; + case GPBDataTypeSFixed32: + valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_); + break; + case GPBDataTypeFloat: + valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_); + break; + case GPBDataTypeFixed64: + valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_); + break; + case GPBDataTypeSFixed64: + valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_); + break; + case GPBDataTypeDouble: + valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_); + break; + case GPBDataTypeInt32: + valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_); + break; + case GPBDataTypeInt64: + valueToFill->valueInt64 = GPBCodedInputStreamReadInt64(&stream->state_); + break; + case GPBDataTypeSInt32: + valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_); + break; + case GPBDataTypeSInt64: + valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_); + break; + case GPBDataTypeUInt32: + valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_); + break; + case GPBDataTypeUInt64: + valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_); + break; + case GPBDataTypeBytes: + [valueToFill->valueData release]; + valueToFill->valueData = GPBCodedInputStreamReadRetainedBytes(&stream->state_); + break; + case GPBDataTypeString: + [valueToFill->valueString release]; + valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_); + break; + case GPBDataTypeMessage: { + GPBMessage *message = [[field.msgClass alloc] init]; + [stream readMessage:message extensionRegistry:registry]; + [valueToFill->valueMessage release]; + valueToFill->valueMessage = message; + break; + } + case GPBDataTypeGroup: + NSCAssert(NO, @"Can't happen"); + break; + case GPBDataTypeEnum: + valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_); + break; + } +} + +void GPBDictionaryReadEntry(id mapDictionary, + GPBCodedInputStream *stream, + GPBExtensionRegistry *registry, + GPBFieldDescriptor *field, + GPBMessage *parentMessage) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + + GPBGenericValue key; + GPBGenericValue value; + // Zero them (but pick up any enum default for proto2). + key.valueString = value.valueString = nil; + if (valueDataType == GPBDataTypeEnum) { + value = field.defaultValue; + } + + GPBCodedInputStreamState *state = &stream->state_; + uint32_t keyTag = + GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO)); + uint32_t valueTag = + GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO)); + + BOOL hitError = NO; + while (YES) { + uint32_t tag = GPBCodedInputStreamReadTag(state); + if (tag == keyTag) { + ReadValue(stream, &key, keyDataType, registry, field); + } else if (tag == valueTag) { + ReadValue(stream, &value, valueDataType, registry, field); + } else if (tag == 0) { + // zero signals EOF / limit reached + break; + } else { // Unknown + if (![stream skipField:tag]){ + hitError = YES; + break; + } + } + } + + if (!hitError) { + // Handle the special defaults and/or missing key/value. + if ((keyDataType == GPBDataTypeString) && (key.valueString == nil)) { + key.valueString = [@"" retain]; + } + if (GPBDataTypeIsObject(valueDataType) && value.valueString == nil) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (valueDataType) { + case GPBDataTypeString: + value.valueString = [@"" retain]; + break; + case GPBDataTypeBytes: + value.valueData = [GPBEmptyNSData() retain]; + break; +#if defined(__clang_analyzer__) + case GPBDataTypeGroup: + // Maps can't really have Groups as the value type, but this case is needed + // so the analyzer won't report the posibility of send nil in for the value + // in the NSMutableDictionary case below. +#endif + case GPBDataTypeMessage: { + value.valueMessage = [[field.msgClass alloc] init]; + break; + } + default: + // Nothing + break; + } +#pragma clang diagnostic pop + } + + if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) { +#if GPB_STATIC_ANALYZER_ONLY(6020053, 7000181) + // Limited to Xcode 6.4 - 7.2, are known to fail here. The upper end can + // be raised as needed for new Xcodes. + // + // This is only needed on a "shallow" analyze; on a "deep" analyze, the + // existing code path gets this correct. In shallow, the analyzer decides + // GPBDataTypeIsObject(valueDataType) is both false and true on a single + // path through this function, allowing nil to be used for the + // setObject:forKey:. + if (value.valueString == nil) { + value.valueString = [@"" retain]; + } +#endif + // mapDictionary is an NSMutableDictionary + [(NSMutableDictionary *)mapDictionary setObject:value.valueString + forKey:key.valueString]; + } else { + if (valueDataType == GPBDataTypeEnum) { + if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) || + [field isValidEnumValue:value.valueEnum]) { + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; + } else { + NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum + forKey:&key + keyDataType:keyDataType]; + [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data]; + } + } else { + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; + } + } + } + + if (GPBDataTypeIsObject(keyDataType)) { + [key.valueString release]; + } + if (GPBDataTypeIsObject(valueDataType)) { + [value.valueString release]; + } +} + +// +// Macros for the common basic cases. +// + +//%PDDM-DEFINE DICTIONARY_IMPL_FOR_POD_KEY(KEY_NAME, KEY_TYPE) +//%DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, , POD) +//%DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, Object, id) + +//%PDDM-DEFINE DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt32, uint32_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int32, int32_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt64, uint64_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int64, int64_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Bool, BOOL, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Float, float, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Double, double, KHELPER) +//%DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, Enum, int32_t, KHELPER) + +//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER) +//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD, VALUE_NAME, value) + +//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, , VALUE_NAME, VALUE_TYPE, POD, OBJECT, Object, object) + +//%PDDM-DEFINE DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary { +//% @package +//% NSMutableDictionary *_dictionary; +//%} +//% +//%- (instancetype)init { +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%- (instancetype)initWith##VNAME##s:(const VALUE_TYPE [])##VNAME_VAR##s +//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP [])keys +//% ##VNAME$S## count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% _dictionary = [[NSMutableDictionary alloc] init]; +//% if (count && VNAME_VAR##s && keys) { +//% for (NSUInteger i = 0; i < count; ++i) { +//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME_VAR##s[i], ______)##DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______) [_dictionary setObject:WRAPPED##VHELPER(VNAME_VAR##s[i]) forKey:WRAPPED##KHELPER(keys[i])]; +//% } +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//% if (self) { +//% if (dictionary) { +//% [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithCapacity:(NSUInteger)numItems { +//% #pragma unused(numItems) +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ) +//% +//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_NAME, VALUE_TYPE, KHELPER) +//% +//%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ) +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER) +//%DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD) +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary { +//% @package +//% NSMutableDictionary *_dictionary; +//% GPBEnumValidationFunc _validationFunc; +//%} +//% +//%@synthesize validationFunc = _validationFunc; +//% +//%- (instancetype)init { +//% return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +//%} +//% +//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { +//% return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +//%} +//% +//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//% rawValues:(const VALUE_TYPE [])rawValues +//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys +//% count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% _dictionary = [[NSMutableDictionary alloc] init]; +//% _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); +//% if (count && rawValues && keys) { +//% for (NSUInteger i = 0; i < count; ++i) { +//%DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______) [_dictionary setObject:WRAPPED##VHELPER(rawValues[i]) forKey:WRAPPED##KHELPER(keys[i])]; +//% } +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWithValidationFunction:dictionary.validationFunc +//% rawValues:NULL +//% forKeys:NULL +//% count:0]; +//% if (self) { +//% if (dictionary) { +//% [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//% capacity:(NSUInteger)numItems { +//% #pragma unused(numItems) +//% return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +//%} +//% +//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Value, value, Raw) +//% +//%- (BOOL)getEnum:(VALUE_TYPE *)value forKey:(KEY_TYPE##KisP$S##KisP)key { +//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% if (wrapped && value) { +//% VALUE_TYPE result = UNWRAP##VALUE_NAME(wrapped); +//% if (!_validationFunc(result)) { +//% result = kGPBUnrecognizedEnumeratorValue; +//% } +//% *value = result; +//% } +//% return (wrapped != NULL); +//%} +//% +//%- (BOOL)getRawValue:(VALUE_TYPE *)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key { +//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% if (wrapped && rawValue) { +//% *rawValue = UNWRAP##VALUE_NAME(wrapped); +//% } +//% return (wrapped != NULL); +//%} +//% +//%- (void)enumerateKeysAndEnumsUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block { +//% GPBEnumValidationFunc func = _validationFunc; +//% BOOL stop = NO; +//% NSEnumerator *keys = [_dictionary keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue = _dictionary[aKey]; +//% VALUE_TYPE unwrapped = UNWRAP##VALUE_NAME(aValue); +//% if (!func(unwrapped)) { +//% unwrapped = kGPBUnrecognizedEnumeratorValue; +//% } +//% block(UNWRAP##KEY_NAME(aKey), unwrapped, &stop); +//% if (stop) { +//% break; +//% } +//% } +//%} +//% +//%DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Value, Enum, value, Raw) +//% +//%- (void)setEnum:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key { +//%DICTIONARY_VALIDATE_KEY_##KHELPER(key, ) if (!_validationFunc(value)) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"GPB##KEY_NAME##VALUE_NAME##Dictionary: Attempt to set an unknown enum value (%d)", +//% value]; +//% } +//% +//% [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ACCESSOR_NAME) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [_dictionary release]; +//% [super dealloc]; +//%} +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { +//% return [[GPB##KEY_NAME##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self]; +//%} +//% +//%- (BOOL)isEqual:(id)other { +//% if (self == other) { +//% return YES; +//% } +//% if (![other isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]) { +//% return NO; +//% } +//% GPB##KEY_NAME##VALUE_NAME##Dictionary *otherDictionary = other; +//% return [_dictionary isEqual:otherDictionary->_dictionary]; +//%} +//% +//%- (NSUInteger)hash { +//% return _dictionary.count; +//%} +//% +//%- (NSString *)description { +//% return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +//%} +//% +//%- (NSUInteger)count { +//% return _dictionary.count; +//%} +//% +//%- (void)enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { +//% BOOL stop = NO; +//% NSDictionary *internal = _dictionary; +//% NSEnumerator *keys = [internal keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey]; +//% block(UNWRAP##KEY_NAME(aKey), UNWRAP##VALUE_NAME(a##VNAME_VAR$u), &stop); +//% if (stop) { +//% break; +//% } +//% } +//%} +//% +//%EXTRA_METHODS_##VHELPER(KEY_NAME, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { +//% NSDictionary *internal = _dictionary; +//% NSUInteger count = internal.count; +//% if (count == 0) { +//% return 0; +//% } +//% +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; +//% size_t result = 0; +//% NSEnumerator *keys = [internal keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey]; +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(a##VNAME_VAR$u), kMapValueFieldNumber, valueDataType); +//% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; +//% } +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); +//% result += tagSize * count; +//% return result; +//%} +//% +//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream +//% asField:(GPBFieldDescriptor *)field { +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; +//% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); +//% NSDictionary *internal = _dictionary; +//% NSEnumerator *keys = [internal keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey]; +//% [outputStream writeInt32NoTag:tag]; +//% // Write the size of the message. +//% KEY_TYPE KisP##unwrappedKey = UNWRAP##KEY_NAME(aKey); +//% VALUE_TYPE unwrappedValue = UNWRAP##VALUE_NAME(a##VNAME_VAR$u); +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); +//% [outputStream writeInt32NoTag:(int32_t)msgSize]; +//% // Write the fields. +//% WriteDict##KEY_NAME##Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); +//% WriteDict##VALUE_NAME##Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); +//% } +//%} +//% +//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { +//% [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)]; +//%} +//% +//%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { +//% [self enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop) { +//% #pragma unused(stop) +//% block(TEXT_FORMAT_OBJ##KEY_NAME(key), TEXT_FORMAT_OBJ##VALUE_NAME(VNAME_VAR)); +//% }]; +//%} +//%PDDM-DEFINE DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ACCESSOR_NAME) +//%DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME, VNAME_VAR, ACCESSOR_NAME) +//%PDDM-DEFINE DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_REMOVE, VNAME_VAR, ACCESSOR_NAME) +//%- (void)add##ACCESSOR_NAME##EntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary { +//% if (otherDictionary) { +//% [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//% } +//%} +//% +//%- (void)set##ACCESSOR_NAME##VNAME##:(VALUE_TYPE)VNAME_VAR forKey:(KEY_TYPE##KisP$S##KisP)key { +//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME_VAR, )##DICTIONARY_VALIDATE_KEY_##KHELPER(key, ) [_dictionary setObject:WRAPPED##VHELPER(VNAME_VAR) forKey:WRAPPED##KHELPER(key)]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%- (void)remove##VNAME_REMOVE##ForKey:(KEY_TYPE##KisP$S##KisP)aKey { +//% [_dictionary removeObjectForKey:WRAPPED##KHELPER(aKey)]; +//%} +//% +//%- (void)removeAll { +//% [_dictionary removeAllObjects]; +//%} + +// +// Custom Generation for Bool keys +// + +//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_POD_IMPL(VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, POD, VALUE_NAME, value) +//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, OBJECT, Object, object) + +//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, HELPER, VNAME, VNAME_VAR) +//%#pragma mark - Bool -> VALUE_NAME +//% +//%@implementation GPBBool##VALUE_NAME##Dictionary { +//% @package +//% VALUE_TYPE _values[2]; +//%BOOL_DICT_HAS_STORAGE_##HELPER()} +//% +//%- (instancetype)init { +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%BOOL_DICT_INITS_##HELPER(VALUE_NAME, VALUE_TYPE) +//% +//%- (instancetype)initWithCapacity:(NSUInteger)numItems { +//% #pragma unused(numItems) +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%BOOL_DICT_DEALLOC##HELPER() +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { +//% return [[GPBBool##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self]; +//%} +//% +//%- (BOOL)isEqual:(id)other { +//% if (self == other) { +//% return YES; +//% } +//% if (![other isKindOfClass:[GPBBool##VALUE_NAME##Dictionary class]]) { +//% return NO; +//% } +//% GPBBool##VALUE_NAME##Dictionary *otherDictionary = other; +//% if ((BOOL_DICT_W_HAS##HELPER(0, ) != BOOL_DICT_W_HAS##HELPER(0, otherDictionary->)) || +//% (BOOL_DICT_W_HAS##HELPER(1, ) != BOOL_DICT_W_HAS##HELPER(1, otherDictionary->))) { +//% return NO; +//% } +//% if ((BOOL_DICT_W_HAS##HELPER(0, ) && (NEQ_##HELPER(_values[0], otherDictionary->_values[0]))) || +//% (BOOL_DICT_W_HAS##HELPER(1, ) && (NEQ_##HELPER(_values[1], otherDictionary->_values[1])))) { +//% return NO; +//% } +//% return YES; +//%} +//% +//%- (NSUInteger)hash { +//% return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0); +//%} +//% +//%- (NSString *)description { +//% NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; +//% if (BOOL_DICT_W_HAS##HELPER(0, )) { +//% [result appendFormat:@"NO: STR_FORMAT_##HELPER(VALUE_NAME)", _values[0]]; +//% } +//% if (BOOL_DICT_W_HAS##HELPER(1, )) { +//% [result appendFormat:@"YES: STR_FORMAT_##HELPER(VALUE_NAME)", _values[1]]; +//% } +//% [result appendString:@" }"]; +//% return result; +//%} +//% +//%- (NSUInteger)count { +//% return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0); +//%} +//% +//%BOOL_VALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE) +//% +//%BOOL_SET_GPBVALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE, VisP) +//% +//%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { +//% if (BOOL_DICT_HAS##HELPER(0, )) { +//% block(@"false", TEXT_FORMAT_OBJ##VALUE_NAME(_values[0])); +//% } +//% if (BOOL_DICT_W_HAS##HELPER(1, )) { +//% block(@"true", TEXT_FORMAT_OBJ##VALUE_NAME(_values[1])); +//% } +//%} +//% +//%- (void)enumerateKeysAnd##VNAME##sUsingBlock: +//% (void (NS_NOESCAPE ^)(BOOL key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { +//% BOOL stop = NO; +//% if (BOOL_DICT_HAS##HELPER(0, )) { +//% block(NO, _values[0], &stop); +//% } +//% if (!stop && BOOL_DICT_W_HAS##HELPER(1, )) { +//% block(YES, _values[1], &stop); +//% } +//%} +//% +//%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% NSUInteger count = 0; +//% size_t result = 0; +//% for (int i = 0; i < 2; ++i) { +//% if (BOOL_DICT_HAS##HELPER(i, )) { +//% ++count; +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); +//% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; +//% } +//% } +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); +//% result += tagSize * count; +//% return result; +//%} +//% +//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream +//% asField:(GPBFieldDescriptor *)field { +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); +//% for (int i = 0; i < 2; ++i) { +//% if (BOOL_DICT_HAS##HELPER(i, )) { +//% // Write the tag. +//% [outputStream writeInt32NoTag:tag]; +//% // Write the size of the message. +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); +//% [outputStream writeInt32NoTag:(int32_t)msgSize]; +//% // Write the fields. +//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); +//% } +//% } +//%} +//% +//%BOOL_DICT_MUTATIONS_##HELPER(VALUE_NAME, VALUE_TYPE) +//% +//%@end +//% + + +// +// Helpers for PODs +// + +//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER) +//%- (BOOL)get##VALUE_NAME##:(nullable VALUE_TYPE *)value forKey:(KEY_TYPE)key { +//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% if (wrapped && value) { +//% *value = UNWRAP##VALUE_NAME(wrapped); +//% } +//% return (wrapped != NULL); +//%} +//%PDDM-DEFINE WRAPPEDPOD(VALUE) +//%@(VALUE) +//%PDDM-DEFINE UNWRAPUInt32(VALUE) +//%[VALUE unsignedIntValue] +//%PDDM-DEFINE UNWRAPInt32(VALUE) +//%[VALUE intValue] +//%PDDM-DEFINE UNWRAPUInt64(VALUE) +//%[VALUE unsignedLongLongValue] +//%PDDM-DEFINE UNWRAPInt64(VALUE) +//%[VALUE longLongValue] +//%PDDM-DEFINE UNWRAPBool(VALUE) +//%[VALUE boolValue] +//%PDDM-DEFINE UNWRAPFloat(VALUE) +//%[VALUE floatValue] +//%PDDM-DEFINE UNWRAPDouble(VALUE) +//%[VALUE doubleValue] +//%PDDM-DEFINE UNWRAPEnum(VALUE) +//%[VALUE intValue] +//%PDDM-DEFINE TEXT_FORMAT_OBJUInt32(VALUE) +//%[NSString stringWithFormat:@"%u", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJInt32(VALUE) +//%[NSString stringWithFormat:@"%d", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJUInt64(VALUE) +//%[NSString stringWithFormat:@"%llu", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJInt64(VALUE) +//%[NSString stringWithFormat:@"%lld", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJBool(VALUE) +//%(VALUE ? @"true" : @"false") +//%PDDM-DEFINE TEXT_FORMAT_OBJFloat(VALUE) +//%[NSString stringWithFormat:@"%.*g", FLT_DIG, VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJDouble(VALUE) +//%[NSString stringWithFormat:@"%.*lg", DBL_DIG, VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJEnum(VALUE) +//%@(VALUE) +//%PDDM-DEFINE ENUM_TYPEPOD(TYPE) +//%NSNumber * +//%PDDM-DEFINE NEQ_POD(VAL1, VAL2) +//%VAL1 != VAL2 +//%PDDM-DEFINE EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME) +// Empty +//%PDDM-DEFINE BOOL_EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD(KEY_NAME, VALUE_NAME) +//%SERIAL_DATA_FOR_ENTRY_POD_##VALUE_NAME(KEY_NAME) +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt32(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int32(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt64(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int64(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Bool(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Float(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Double(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Enum(KEY_NAME) +//%- (NSData *)serializedDataForUnknownValue:(int32_t)value +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType { +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); +//% NSMutableData *data = [NSMutableData dataWithLength:msgSize]; +//% GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; +//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); +//% [outputStream release]; +//% return data; +//%} +//% +//%PDDM-DEFINE GPBVALUE_POD(VALUE_NAME) +//%value##VALUE_NAME +//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_POD(VALUE_NAME, EXTRA_INDENT) +// Empty +//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_POD(KEY_NAME, EXTRA_INDENT) +// Empty + +//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_POD() +//% BOOL _valueSet[2]; +//% +//%PDDM-DEFINE BOOL_DICT_INITS_POD(VALUE_NAME, VALUE_TYPE) +//%- (instancetype)initWith##VALUE_NAME##s:(const VALUE_TYPE [])values +//% ##VALUE_NAME$S## forKeys:(const BOOL [])keys +//% ##VALUE_NAME$S## count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% for (NSUInteger i = 0; i < count; ++i) { +//% int idx = keys[i] ? 1 : 0; +//% _values[idx] = values[i]; +//% _valueSet[idx] = YES; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWith##VALUE_NAME##s:NULL forKeys:NULL count:0]; +//% if (self) { +//% if (dictionary) { +//% for (int i = 0; i < 2; ++i) { +//% if (dictionary->_valueSet[i]) { +//% _values[i] = dictionary->_values[i]; +//% _valueSet[i] = YES; +//% } +//% } +//% } +//% } +//% return self; +//%} +//%PDDM-DEFINE BOOL_DICT_DEALLOCPOD() +//%#if !defined(NS_BLOCK_ASSERTIONS) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [super dealloc]; +//%} +//%#endif // !defined(NS_BLOCK_ASSERTIONS) +//%PDDM-DEFINE BOOL_DICT_W_HASPOD(IDX, REF) +//%BOOL_DICT_HASPOD(IDX, REF) +//%PDDM-DEFINE BOOL_DICT_HASPOD(IDX, REF) +//%REF##_valueSet[IDX] +//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE) +//%- (BOOL)get##VALUE_NAME##:(VALUE_TYPE *)value forKey:(BOOL)key { +//% int idx = (key ? 1 : 0); +//% if (_valueSet[idx]) { +//% if (value) { +//% *value = _values[idx]; +//% } +//% return YES; +//% } +//% return NO; +//%} +//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP) +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { +//% int idx = (key->valueBool ? 1 : 0); +//% _values[idx] = value->value##VALUE_NAME; +//% _valueSet[idx] = YES; +//%} +//%PDDM-DEFINE BOOL_DICT_MUTATIONS_POD(VALUE_NAME, VALUE_TYPE) +//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary { +//% if (otherDictionary) { +//% for (int i = 0; i < 2; ++i) { +//% if (otherDictionary->_valueSet[i]) { +//% _valueSet[i] = YES; +//% _values[i] = otherDictionary->_values[i]; +//% } +//% } +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//% } +//%} +//% +//%- (void)set##VALUE_NAME:(VALUE_TYPE)value forKey:(BOOL)key { +//% int idx = (key ? 1 : 0); +//% _values[idx] = value; +//% _valueSet[idx] = YES; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%- (void)remove##VALUE_NAME##ForKey:(BOOL)aKey { +//% _valueSet[aKey ? 1 : 0] = NO; +//%} +//% +//%- (void)removeAll { +//% _valueSet[0] = NO; +//% _valueSet[1] = NO; +//%} +//%PDDM-DEFINE STR_FORMAT_POD(VALUE_NAME) +//%STR_FORMAT_##VALUE_NAME() +//%PDDM-DEFINE STR_FORMAT_UInt32() +//%%u +//%PDDM-DEFINE STR_FORMAT_Int32() +//%%d +//%PDDM-DEFINE STR_FORMAT_UInt64() +//%%llu +//%PDDM-DEFINE STR_FORMAT_Int64() +//%%lld +//%PDDM-DEFINE STR_FORMAT_Bool() +//%%d +//%PDDM-DEFINE STR_FORMAT_Float() +//%%f +//%PDDM-DEFINE STR_FORMAT_Double() +//%%lf + +// +// Helpers for Objects +// + +//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER) +//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key { +//% VALUE_TYPE result = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% return result; +//%} +//%PDDM-DEFINE WRAPPEDOBJECT(VALUE) +//%VALUE +//%PDDM-DEFINE UNWRAPString(VALUE) +//%VALUE +//%PDDM-DEFINE UNWRAPObject(VALUE) +//%VALUE +//%PDDM-DEFINE TEXT_FORMAT_OBJString(VALUE) +//%VALUE +//%PDDM-DEFINE TEXT_FORMAT_OBJObject(VALUE) +//%VALUE +//%PDDM-DEFINE ENUM_TYPEOBJECT(TYPE) +//%ENUM_TYPEOBJECT_##TYPE() +//%PDDM-DEFINE ENUM_TYPEOBJECT_NSString() +//%NSString * +//%PDDM-DEFINE ENUM_TYPEOBJECT_id() +//%id ## +//%PDDM-DEFINE NEQ_OBJECT(VAL1, VAL2) +//%![VAL1 isEqual:VAL2] +//%PDDM-DEFINE EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME) +//%- (BOOL)isInitialized { +//% for (GPBMessage *msg in [_dictionary objectEnumerator]) { +//% if (!msg.initialized) { +//% return NO; +//% } +//% } +//% return YES; +//%} +//% +//%- (instancetype)deepCopyWithZone:(NSZone *)zone { +//% GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict = +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; +//% NSEnumerator *keys = [_dictionary keyEnumerator]; +//% id aKey; +//% NSMutableDictionary *internalDict = newDict->_dictionary; +//% while ((aKey = [keys nextObject])) { +//% GPBMessage *msg = _dictionary[aKey]; +//% GPBMessage *copiedMsg = [msg copyWithZone:zone]; +//% [internalDict setObject:copiedMsg forKey:aKey]; +//% [copiedMsg release]; +//% } +//% return newDict; +//%} +//% +//% +//%PDDM-DEFINE BOOL_EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME) +//%- (BOOL)isInitialized { +//% if (_values[0] && ![_values[0] isInitialized]) { +//% return NO; +//% } +//% if (_values[1] && ![_values[1] isInitialized]) { +//% return NO; +//% } +//% return YES; +//%} +//% +//%- (instancetype)deepCopyWithZone:(NSZone *)zone { +//% GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict = +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; +//% for (int i = 0; i < 2; ++i) { +//% if (_values[i] != nil) { +//% newDict->_values[i] = [_values[i] copyWithZone:zone]; +//% } +//% } +//% return newDict; +//%} +//% +//% +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_OBJECT(KEY_NAME, VALUE_NAME) +// Empty +//%PDDM-DEFINE GPBVALUE_OBJECT(VALUE_NAME) +//%valueString +//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_OBJECT(VALUE_NAME, EXTRA_INDENT) +//%##EXTRA_INDENT$S## if (!##VALUE_NAME) { +//%##EXTRA_INDENT$S## [NSException raise:NSInvalidArgumentException +//%##EXTRA_INDENT$S## format:@"Attempting to add nil object to a Dictionary"]; +//%##EXTRA_INDENT$S## } +//% +//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_OBJECT(KEY_NAME, EXTRA_INDENT) +//%##EXTRA_INDENT$S## if (!##KEY_NAME) { +//%##EXTRA_INDENT$S## [NSException raise:NSInvalidArgumentException +//%##EXTRA_INDENT$S## format:@"Attempting to add nil key to a Dictionary"]; +//%##EXTRA_INDENT$S## } +//% + +//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_OBJECT() +// Empty +//%PDDM-DEFINE BOOL_DICT_INITS_OBJECT(VALUE_NAME, VALUE_TYPE) +//%- (instancetype)initWithObjects:(const VALUE_TYPE [])objects +//% forKeys:(const BOOL [])keys +//% count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% for (NSUInteger i = 0; i < count; ++i) { +//% if (!objects[i]) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"Attempting to add nil object to a Dictionary"]; +//% } +//% int idx = keys[i] ? 1 : 0; +//% [_values[idx] release]; +//% _values[idx] = (VALUE_TYPE)[objects[i] retain]; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWithObjects:NULL forKeys:NULL count:0]; +//% if (self) { +//% if (dictionary) { +//% _values[0] = [dictionary->_values[0] retain]; +//% _values[1] = [dictionary->_values[1] retain]; +//% } +//% } +//% return self; +//%} +//%PDDM-DEFINE BOOL_DICT_DEALLOCOBJECT() +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [_values[0] release]; +//% [_values[1] release]; +//% [super dealloc]; +//%} +//%PDDM-DEFINE BOOL_DICT_W_HASOBJECT(IDX, REF) +//%(BOOL_DICT_HASOBJECT(IDX, REF)) +//%PDDM-DEFINE BOOL_DICT_HASOBJECT(IDX, REF) +//%REF##_values[IDX] != nil +//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE) +//%- (VALUE_TYPE)objectForKey:(BOOL)key { +//% return _values[key ? 1 : 0]; +//%} +//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE, VisP) +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { +//% int idx = (key->valueBool ? 1 : 0); +//% [_values[idx] release]; +//% _values[idx] = [value->valueString retain]; +//%} + +//%PDDM-DEFINE BOOL_DICT_MUTATIONS_OBJECT(VALUE_NAME, VALUE_TYPE) +//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary { +//% if (otherDictionary) { +//% for (int i = 0; i < 2; ++i) { +//% if (otherDictionary->_values[i] != nil) { +//% [_values[i] release]; +//% _values[i] = [otherDictionary->_values[i] retain]; +//% } +//% } +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//% } +//%} +//% +//%- (void)setObject:(VALUE_TYPE)object forKey:(BOOL)key { +//% if (!object) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"Attempting to add nil object to a Dictionary"]; +//% } +//% int idx = (key ? 1 : 0); +//% [_values[idx] release]; +//% _values[idx] = [object retain]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%- (void)removeObjectForKey:(BOOL)aKey { +//% int idx = (aKey ? 1 : 0); +//% [_values[idx] release]; +//% _values[idx] = nil; +//%} +//% +//%- (void)removeAll { +//% for (int i = 0; i < 2; ++i) { +//% [_values[i] release]; +//% _values[i] = nil; +//% } +//%} +//%PDDM-DEFINE STR_FORMAT_OBJECT(VALUE_NAME) +//%%@ + + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt32 -> UInt32 + +@implementation GPBUInt32UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32UInt32Dictionary class]]) { + return NO; + } + GPBUInt32UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(uint32_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Int32 + +@implementation GPBUInt32Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32Int32Dictionary class]]) { + return NO; + } + GPBUInt32Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> UInt64 + +@implementation GPBUInt32UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32UInt64Dictionary class]]) { + return NO; + } + GPBUInt32UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(uint32_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Int64 + +@implementation GPBUInt32Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32Int64Dictionary class]]) { + return NO; + } + GPBUInt32Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(uint32_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Bool + +@implementation GPBUInt32BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32BoolDictionary class]]) { + return NO; + } + GPBUInt32BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(uint32_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Float + +@implementation GPBUInt32FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32FloatDictionary class]]) { + return NO; + } + GPBUInt32FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(uint32_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Double + +@implementation GPBUInt32DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32DoubleDictionary class]]) { + return NO; + } + GPBUInt32DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(uint32_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Enum + +@implementation GPBUInt32EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32EnumDictionary class]]) { + return NO; + } + GPBUInt32EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey unsignedIntValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(uint32_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBUInt32EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - UInt32 -> Object + +@implementation GPBUInt32ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32ObjectDictionary class]]) { + return NO; + } + GPBUInt32ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey unsignedIntValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBUInt32ObjectDictionary *newDict = + [[GPBUInt32ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(uint32_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], object); + }]; +} + +- (id)objectForKey:(uint32_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(uint32_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 -> UInt32 + +@implementation GPBInt32UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32UInt32Dictionary class]]) { + return NO; + } + GPBInt32UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(int32_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Int32 + +@implementation GPBInt32Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32Int32Dictionary class]]) { + return NO; + } + GPBInt32Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(int32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> UInt64 + +@implementation GPBInt32UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32UInt64Dictionary class]]) { + return NO; + } + GPBInt32UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(int32_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Int64 + +@implementation GPBInt32Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32Int64Dictionary class]]) { + return NO; + } + GPBInt32Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(int32_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Bool + +@implementation GPBInt32BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32BoolDictionary class]]) { + return NO; + } + GPBInt32BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(int32_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Float + +@implementation GPBInt32FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32FloatDictionary class]]) { + return NO; + } + GPBInt32FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(int32_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Double + +@implementation GPBInt32DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32DoubleDictionary class]]) { + return NO; + } + GPBInt32DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(int32_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Enum + +@implementation GPBInt32EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32EnumDictionary class]]) { + return NO; + } + GPBInt32EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey intValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(int32_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBInt32EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - Int32 -> Object + +@implementation GPBInt32ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32ObjectDictionary class]]) { + return NO; + } + GPBInt32ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey intValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBInt32ObjectDictionary *newDict = + [[GPBInt32ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(int32_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], object); + }]; +} + +- (id)objectForKey:(int32_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(int32_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt64 -> UInt32 + +@implementation GPBUInt64UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64UInt32Dictionary class]]) { + return NO; + } + GPBUInt64UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(uint64_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Int32 + +@implementation GPBUInt64Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64Int32Dictionary class]]) { + return NO; + } + GPBUInt64Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> UInt64 + +@implementation GPBUInt64UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64UInt64Dictionary class]]) { + return NO; + } + GPBUInt64UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(uint64_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Int64 + +@implementation GPBUInt64Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64Int64Dictionary class]]) { + return NO; + } + GPBUInt64Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(uint64_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Bool + +@implementation GPBUInt64BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64BoolDictionary class]]) { + return NO; + } + GPBUInt64BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(uint64_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Float + +@implementation GPBUInt64FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64FloatDictionary class]]) { + return NO; + } + GPBUInt64FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(uint64_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Double + +@implementation GPBUInt64DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64DoubleDictionary class]]) { + return NO; + } + GPBUInt64DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(uint64_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Enum + +@implementation GPBUInt64EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64EnumDictionary class]]) { + return NO; + } + GPBUInt64EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey unsignedLongLongValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(uint64_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBUInt64EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - UInt64 -> Object + +@implementation GPBUInt64ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64ObjectDictionary class]]) { + return NO; + } + GPBUInt64ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey unsignedLongLongValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBUInt64ObjectDictionary *newDict = + [[GPBUInt64ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(uint64_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], object); + }]; +} + +- (id)objectForKey:(uint64_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(uint64_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int64 -> UInt32 + +@implementation GPBInt64UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64UInt32Dictionary class]]) { + return NO; + } + GPBInt64UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(int64_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Int32 + +@implementation GPBInt64Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64Int32Dictionary class]]) { + return NO; + } + GPBInt64Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(int64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> UInt64 + +@implementation GPBInt64UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64UInt64Dictionary class]]) { + return NO; + } + GPBInt64UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(int64_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Int64 + +@implementation GPBInt64Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64Int64Dictionary class]]) { + return NO; + } + GPBInt64Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(int64_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Bool + +@implementation GPBInt64BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64BoolDictionary class]]) { + return NO; + } + GPBInt64BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(int64_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Float + +@implementation GPBInt64FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64FloatDictionary class]]) { + return NO; + } + GPBInt64FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(int64_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Double + +@implementation GPBInt64DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64DoubleDictionary class]]) { + return NO; + } + GPBInt64DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(int64_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Enum + +@implementation GPBInt64EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64EnumDictionary class]]) { + return NO; + } + GPBInt64EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey longLongValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(int64_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBInt64EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - Int64 -> Object + +@implementation GPBInt64ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64ObjectDictionary class]]) { + return NO; + } + GPBInt64ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey longLongValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBInt64ObjectDictionary *newDict = + [[GPBInt64ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(int64_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], object); + }]; +} + +- (id)objectForKey:(int64_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(int64_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_POD_IMPL_FOR_KEY(String, NSString, *, OBJECT) +// This block of code is generated, do not edit it directly. + +#pragma mark - String -> UInt32 + +@implementation GPBStringUInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringUInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringUInt32Dictionary class]]) { + return NO; + } + GPBStringUInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(NSString *key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Int32 + +@implementation GPBStringInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringInt32Dictionary class]]) { + return NO; + } + GPBStringInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(NSString *key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> UInt64 + +@implementation GPBStringUInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringUInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringUInt64Dictionary class]]) { + return NO; + } + GPBStringUInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(NSString *key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Int64 + +@implementation GPBStringInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringInt64Dictionary class]]) { + return NO; + } + GPBStringInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(NSString *key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Bool + +@implementation GPBStringBoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringBoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringBoolDictionary class]]) { + return NO; + } + GPBStringBoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(NSString *key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block(key, (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Float + +@implementation GPBStringFloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringFloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringFloatDictionary class]]) { + return NO; + } + GPBStringFloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(NSString *key, float value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Double + +@implementation GPBStringDoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringDoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringDoubleDictionary class]]) { + return NO; + } + GPBStringDoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(NSString *key, double value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Enum + +@implementation GPBStringEnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(rawValues[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringEnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringEnumDictionary class]]) { + return NO; + } + GPBStringEnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block(key, @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block(aKey, unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBStringEnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +//%PDDM-EXPAND-END (5 expansions) + + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> UInt32 + +@implementation GPBBoolUInt32Dictionary { + @package + uint32_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolUInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolUInt32Dictionary class]]) { + return NO; + } + GPBBoolUInt32Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %u", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %u", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getUInt32:(uint32_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueUInt32; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%u", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%u", _values[1]]); + } +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Int32 + +@implementation GPBBoolInt32Dictionary { + @package + int32_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolInt32Dictionary class]]) { + return NO; + } + GPBBoolInt32Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %d", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %d", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getInt32:(int32_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueInt32; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%d", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%d", _values[1]]); + } +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> UInt64 + +@implementation GPBBoolUInt64Dictionary { + @package + uint64_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolUInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolUInt64Dictionary class]]) { + return NO; + } + GPBBoolUInt64Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %llu", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %llu", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getUInt64:(uint64_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueUInt64; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%llu", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%llu", _values[1]]); + } +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Int64 + +@implementation GPBBoolInt64Dictionary { + @package + int64_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolInt64Dictionary class]]) { + return NO; + } + GPBBoolInt64Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %lld", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %lld", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getInt64:(int64_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueInt64; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%lld", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%lld", _values[1]]); + } +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Bool, BOOL) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Bool + +@implementation GPBBoolBoolDictionary { + @package + BOOL _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolBoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolBoolDictionary class]]) { + return NO; + } + GPBBoolBoolDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %d", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %d", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getBool:(BOOL *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueBool; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", (_values[0] ? @"true" : @"false")); + } + if (_valueSet[1]) { + block(@"true", (_values[1] ? @"true" : @"false")); + } +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Float, float) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Float + +@implementation GPBBoolFloatDictionary { + @package + float _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolFloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolFloatDictionary class]]) { + return NO; + } + GPBBoolFloatDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %f", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %f", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getFloat:(float *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueFloat; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[1]]); + } +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, float value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Double, double) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Double + +@implementation GPBBoolDoubleDictionary { + @package + double _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolDoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolDoubleDictionary class]]) { + return NO; + } + GPBBoolDoubleDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %lf", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %lf", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getDouble:(double *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueDouble; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[1]]); + } +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, double value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(Object, id) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Object + +@implementation GPBBoolObjectDictionary { + @package + id _values[2]; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + int idx = keys[i] ? 1 : 0; + [_values[idx] release]; + _values[idx] = (id)[objects[i] retain]; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + _values[0] = [dictionary->_values[0] retain]; + _values[1] = [dictionary->_values[1] retain]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_values[0] release]; + [_values[1] release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolObjectDictionary class]]) { + return NO; + } + GPBBoolObjectDictionary *otherDictionary = other; + if (((_values[0] != nil) != (otherDictionary->_values[0] != nil)) || + ((_values[1] != nil) != (otherDictionary->_values[1] != nil))) { + return NO; + } + if (((_values[0] != nil) && (![_values[0] isEqual:otherDictionary->_values[0]])) || + ((_values[1] != nil) && (![_values[1] isEqual:otherDictionary->_values[1]]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if ((_values[0] != nil)) { + [result appendFormat:@"NO: %@", _values[0]]; + } + if ((_values[1] != nil)) { + [result appendFormat:@"YES: %@", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0); +} + +- (id)objectForKey:(BOOL)key { + return _values[key ? 1 : 0]; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + [_values[idx] release]; + _values[idx] = [value->valueString retain]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_values[0] != nil) { + block(@"false", _values[0]); + } + if ((_values[1] != nil)) { + block(@"true", _values[1]); + } +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, id object, BOOL *stop))block { + BOOL stop = NO; + if (_values[0] != nil) { + block(NO, _values[0], &stop); + } + if (!stop && (_values[1] != nil)) { + block(YES, _values[1], &stop); + } +} + +- (BOOL)isInitialized { + if (_values[0] && ![_values[0] isInitialized]) { + return NO; + } + if (_values[1] && ![_values[1] isInitialized]) { + return NO; + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBBoolObjectDictionary *newDict = + [[GPBBoolObjectDictionary alloc] init]; + for (int i = 0; i < 2; ++i) { + if (_values[i] != nil) { + newDict->_values[i] = [_values[i] copyWithZone:zone]; + } + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_values[i] != nil) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_values[i] != nil) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_values[i] != nil) { + [_values[i] release]; + _values[i] = [otherDictionary->_values[i] retain]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(BOOL)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + int idx = (key ? 1 : 0); + [_values[idx] release]; + _values[idx] = [object retain]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(BOOL)aKey { + int idx = (aKey ? 1 : 0); + [_values[idx] release]; + _values[idx] = nil; +} + +- (void)removeAll { + for (int i = 0; i < 2; ++i) { + [_values[i] release]; + _values[i] = nil; + } +} + +@end + +//%PDDM-EXPAND-END (8 expansions) + +#pragma mark - Bool -> Enum + +@implementation GPBBoolEnumDictionary { + @package + GPBEnumValidationFunc _validationFunc; + int32_t _values[2]; + BOOL _valueSet[2]; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = rawValues[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { +#pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolEnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolEnumDictionary class]]) { + return NO; + } + GPBBoolEnumDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %d", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %d", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getEnum:(int32_t*)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + int32_t result = _values[idx]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return YES; + } + return NO; +} + +- (BOOL)getRawValue:(int32_t*)rawValue forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (rawValue) { + *rawValue = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block { + BOOL stop = NO; + GPBEnumValidationFunc func = _validationFunc; + int32_t validatedValue; + if (_valueSet[0]) { + validatedValue = _values[0]; + if (!func(validatedValue)) { + validatedValue = kGPBUnrecognizedEnumeratorValue; + } + block(NO, validatedValue, &stop); + } + if (!stop && _valueSet[1]) { + validatedValue = _values[1]; + if (!func(validatedValue)) { + validatedValue = kGPBUnrecognizedEnumeratorValue; + } + block(YES, validatedValue, &stop); + } +} + +//%PDDM-EXPAND SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) +// This block of code is generated, do not edit it directly. + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} + +//%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", @(_values[0])); + } + if (_valueSet[1]) { + block(@"true", @(_values[1])); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueInt32; + _valueSet[idx] = YES; +} + +- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setEnum:(int32_t)value forKey:(BOOL)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBBoolEnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = rawValue; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +#pragma mark - NSDictionary Subclass + +@implementation GPBAutocreatedDictionary { + NSMutableDictionary *_dictionary; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +#pragma mark Required NSDictionary overrides + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const id [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] initWithObjects:objects + forKeys:keys + count:count]; + } + return self; +} + +- (NSUInteger)count { + return [_dictionary count]; +} + +- (id)objectForKey:(id)aKey { + return [_dictionary objectForKey:aKey]; +} + +- (NSEnumerator *)keyEnumerator { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + return [_dictionary keyEnumerator]; +} + +#pragma mark Required NSMutableDictionary overrides + +// Only need to call GPBAutocreatedDictionaryModified() when adding things +// since we only autocreate empty dictionaries. + +- (void)setObject:(id)anObject forKey:(id)aKey { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + [_dictionary setObject:anObject forKey:aKey]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(id)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +#pragma mark Extra things hooked + +- (id)copyWithZone:(NSZone *)zone { + if (_dictionary == nil) { + return [[NSMutableDictionary allocWithZone:zone] init]; + } + return [_dictionary copyWithZone:zone]; +} + +- (id)mutableCopyWithZone:(NSZone *)zone { + if (_dictionary == nil) { + return [[NSMutableDictionary allocWithZone:zone] init]; + } + return [_dictionary mutableCopyWithZone:zone]; +} + +// Not really needed, but subscripting is likely common enough it doesn't hurt +// to ensure it goes directly to the real NSMutableDictionary. +- (id)objectForKeyedSubscript:(id)key { + return [_dictionary objectForKeyedSubscript:key]; +} + +// Not really needed, but subscripting is likely common enough it doesn't hurt +// to ensure it goes directly to the real NSMutableDictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + [_dictionary setObject:obj forKeyedSubscript:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)enumerateKeysAndObjectsUsingBlock:(void (NS_NOESCAPE ^)(id key, + id obj, + BOOL *stop))block { + [_dictionary enumerateKeysAndObjectsUsingBlock:block]; +} + +- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(id key, + id obj, + BOOL *stop))block { + [_dictionary enumerateKeysAndObjectsWithOptions:opts usingBlock:block]; +} + +@end + +#pragma clang diagnostic pop diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary_PackagePrivate.h new file mode 100644 index 0000000..7b921e8 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBDictionary_PackagePrivate.h @@ -0,0 +1,488 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBDictionary.h" + +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionRegistry; +@class GPBFieldDescriptor; + +@protocol GPBDictionaryInternalsProtocol +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field; +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key; +- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@end + +//%PDDM-DEFINE DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(KEY_NAME) +//%DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Object, Object) +//%PDDM-DEFINE DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt32, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int32, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt64, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int64, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Bool, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Float, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Double, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Enum, Enum) + +//%PDDM-DEFINE DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, VALUE_NAME, HELPER) +//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary () { +//% @package +//% GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +//%} +//%EXTRA_DICTIONARY_PRIVATE_INTERFACES_##HELPER()@end +//% + +//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Basic() +// Empty +//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Object() +//%- (BOOL)isInitialized; +//%- (instancetype)deepCopyWithZone:(NSZone *)zone +//% __attribute__((ns_returns_retained)); +//% +//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum() +//%- (NSData *)serializedDataForUnknownValue:(int32_t)value +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType; +//% + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32) +// This block of code is generated, do not edit it directly. + +@interface GPBUInt32UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBUInt32ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32) +// This block of code is generated, do not edit it directly. + +@interface GPBInt32UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBInt32ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64) +// This block of code is generated, do not edit it directly. + +@interface GPBUInt64UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBUInt64ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64) +// This block of code is generated, do not edit it directly. + +@interface GPBInt64UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBInt64ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool) +// This block of code is generated, do not edit it directly. + +@interface GPBBoolUInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolUInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolBoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolFloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolDoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolEnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBBoolObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String) +// This block of code is generated, do not edit it directly. + +@interface GPBStringUInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringUInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringBoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringFloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringDoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringEnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +//%PDDM-EXPAND-END (6 expansions) + +#pragma mark - NSDictionary Subclass + +@interface GPBAutocreatedDictionary : NSMutableDictionary { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Helpers + +CF_EXTERN_C_BEGIN + +// Helper to compute size when an NSDictionary is used for the map instead +// of a custom type. +size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, + GPBFieldDescriptor *field); + +// Helper to write out when an NSDictionary is used for the map instead +// of a custom type. +void GPBDictionaryWriteToStreamInternalHelper( + GPBCodedOutputStream *outputStream, NSDictionary *dict, + GPBFieldDescriptor *field); + +// Helper to check message initialization when an NSDictionary is used for +// the map instead of a custom type. +BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, + GPBFieldDescriptor *field); + +// Helper to read a map instead. +void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream, + GPBExtensionRegistry *registry, + GPBFieldDescriptor *field, + GPBMessage *parentMessage); + +CF_EXTERN_C_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionInternals.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionInternals.h new file mode 100644 index 0000000..2b980ae --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionInternals.h @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBDescriptor.h" + +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionRegistry; + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message); + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value); + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output); diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionInternals.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionInternals.m new file mode 100644 index 0000000..290c82a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionInternals.m @@ -0,0 +1,391 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBExtensionInternals.h" + +#import + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) + __attribute__((ns_returns_retained)); + +GPB_INLINE size_t DataTypeSize(GPBDataType dataType) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (dataType) { + case GPBDataTypeBool: + return 1; + case GPBDataTypeFixed32: + case GPBDataTypeSFixed32: + case GPBDataTypeFloat: + return 4; + case GPBDataTypeFixed64: + case GPBDataTypeSFixed64: + case GPBDataTypeDouble: + return 8; + default: + return 0; + } +#pragma clang diagnostic pop +} + +static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag(object); + switch (dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + FIELD_CASE2(Group) + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static size_t ComputeSerializedSizeIncludingTagOfObject( + GPBExtensionDescription *description, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, \ + [(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, object); + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(description)) { + return GPBComputeMessageSetExtensionSize(description->fieldNumber, + object); + } else { + return GPBComputeMessageSize(description->fieldNumber, object); + } + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static size_t ComputeSerializedSizeIncludingTagOfArray( + GPBExtensionDescription *description, NSArray *values) { + if (GPBExtensionIsPacked(description)) { + size_t size = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + size = values.count * typeSize; + } else { + for (id value in values) { + size += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + return size + GPBComputeTagSize(description->fieldNumber) + + GPBComputeRawVarint32SizeForInteger(size); + } else { + size_t size = 0; + for (id value in values) { + size += ComputeSerializedSizeIncludingTagOfObject(description, value); + } + return size; + } +} + +static void WriteObjectIncludingTagToCodedOutputStream( + id object, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber \ + value:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber value:object]; \ + return; + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(description)) { + [output writeMessageSetExtension:description->fieldNumber value:object]; + } else { + [output writeMessage:description->fieldNumber value:object]; + } + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteObjectNoTagToCodedOutputStream( + id object, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:object]; \ + return; + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + case GPBDataTypeGroup: + [output writeGroupNoTag:description->fieldNumber value:object]; + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteArrayIncludingTagsToCodedOutputStream( + NSArray *values, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { + if (GPBExtensionIsPacked(description)) { + [output writeTag:description->fieldNumber + format:GPBWireFormatLengthDelimited]; + size_t dataSize = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + dataSize = values.count * typeSize; + } else { + for (id value in values) { + dataSize += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + [output writeRawVarintSizeTAs32:dataSize]; + for (id value in values) { + WriteObjectNoTagToCodedOutputStream(value, description, output); + } + } else { + for (id value in values) { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } + } +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + if (isPackedOnStream) { + NSCAssert(GPBExtensionIsRepeated(description), + @"How was it packed if it isn't repeated?"); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + nil); + [message addExtension:extension value:value]; + [value release]; + } + GPBCodedInputStreamPopLimit(state, limit); + } else { + id existingValue = nil; + BOOL isRepeated = GPBExtensionIsRepeated(description); + if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) { + existingValue = [message getExistingExtension:extension]; + } + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + existingValue); + if (isRepeated) { + [message addExtension:extension value:value]; + } else { + [message setExtension:extension value:value]; + } + [value release]; + } +} + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + WriteArrayIncludingTagsToCodedOutputStream(value, description, output); + } else { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } +} + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + return ComputeSerializedSizeIncludingTagOfArray(description, value); + } else { + return ComputeSerializedSizeIncludingTagOfObject(description, value); + } +} + +// Note that this returns a retained value intentionally. +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + switch (description->dataType) { + case GPBDataTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)]; + case GPBDataTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)]; + case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)]; + case GPBDataTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)]; + case GPBDataTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)]; + case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)]; + case GPBDataTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)]; + case GPBDataTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)]; + case GPBDataTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)]; + case GPBDataTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)]; + case GPBDataTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)]; + case GPBDataTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)]; + case GPBDataTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)]; + case GPBDataTypeBytes: return GPBCodedInputStreamReadRetainedBytes(state); + case GPBDataTypeString: return GPBCodedInputStreamReadRetainedString(state); + case GPBDataTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)]; + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + GPBMessage *message; + if (existingValue) { + message = [existingValue retain]; + } else { + GPBDescriptor *decriptor = [extension.msgClass descriptor]; + message = [[decriptor.messageClass alloc] init]; + } + + if (description->dataType == GPBDataTypeGroup) { + [input readGroup:description->fieldNumber + message:message + extensionRegistry:extensionRegistry]; + } else { + // description->dataType == GPBDataTypeMessage + if (GPBExtensionIsWireFormat(description)) { + // For MessageSet fields the message length will have already been + // read. + [message mergeFromCodedInputStream:input + extensionRegistry:extensionRegistry]; + } else { + [input readMessage:message extensionRegistry:extensionRegistry]; + } + } + + return message; + } + } + + return nil; +} + +#pragma clang diagnostic pop diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.h new file mode 100644 index 0000000..d79632d --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.h @@ -0,0 +1,87 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBDescriptor; +@class GPBExtensionDescriptor; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A table of known extensions, searchable by name or field number. When + * parsing a protocol message that might have extensions, you must provide a + * GPBExtensionRegistry in which you have registered any extensions that you + * want to be able to parse. Otherwise, those extensions will just be treated + * like unknown fields. + * + * The *Root classes provide `+extensionRegistry` for the extensions defined + * in a given file *and* all files it imports. You can also create a + * GPBExtensionRegistry, and merge those registries to handle parsing + * extensions defined from non overlapping files. + * + * ``` + * GPBExtensionRegistry *registry = [[MyProtoFileRoot extensionRegistry] copy]; + * [registry addExtension:[OtherMessage neededExtension]]; // Not in MyProtoFile + * NSError *parseError; + * MyMessage *msg = [MyMessage parseData:data extensionRegistry:registry error:&parseError]; + * ``` + **/ +@interface GPBExtensionRegistry : NSObject + +/** + * Adds the given GPBExtensionDescriptor to this registry. + * + * @param extension The extension description to add. + **/ +- (void)addExtension:(GPBExtensionDescriptor *)extension; + +/** + * Adds all the extensions from another registry to this registry. + * + * @param registry The registry to merge into this registry. + **/ +- (void)addExtensions:(GPBExtensionRegistry *)registry; + +/** + * Looks for the extension registered for the given field number on a given + * GPBDescriptor. + * + * @param descriptor The descriptor to look for a registered extension on. + * @param fieldNumber The field number of the extension to look for. + * + * @return The registered GPBExtensionDescriptor or nil if none was found. + **/ +- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.m new file mode 100644 index 0000000..b056a52 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.m @@ -0,0 +1,130 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBExtensionRegistry.h" + +#import "GPBBootstrap.h" +#import "GPBDescriptor.h" + +@implementation GPBExtensionRegistry { + NSMutableDictionary *mutableClassMap_; +} + +- (instancetype)init { + if ((self = [super init])) { + mutableClassMap_ = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)dealloc { + [mutableClassMap_ release]; + [super dealloc]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (instancetype)copyWithZone:(NSZone *)zone { + GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; + [result addExtensions:self]; + return result; +} + +- (void)addExtension:(GPBExtensionDescriptor *)extension { + if (extension == nil) { + return; + } + + Class containingMessageClass = extension.containingMessageClass; + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + [mutableClassMap_ objectForKey:containingMessageClass]; + if (extensionMap == nil) { + // Use a custom dictionary here because the keys are numbers and conversion + // back and forth from NSNumber isn't worth the cost. + extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, + &kCFTypeDictionaryValueCallBacks); + [mutableClassMap_ setObject:(id)extensionMap + forKey:(id)containingMessageClass]; + CFRelease(extensionMap); + } + + ssize_t key = extension.fieldNumber; + CFDictionarySetValue(extensionMap, (const void *)key, extension); +} + +- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber { + Class messageClass = descriptor.messageClass; + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + [mutableClassMap_ objectForKey:messageClass]; + ssize_t key = fieldNumber; + GPBExtensionDescriptor *result = + (extensionMap + ? CFDictionaryGetValue(extensionMap, (const void *)key) + : nil); + return result; +} + +static void CopyKeyValue(const void *key, const void *value, void *context) { + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)context; + CFDictionarySetValue(extensionMap, key, value); +} + +- (void)addExtensions:(GPBExtensionRegistry *)registry { + if (registry == nil) { + // In the case where there are no extensions just ignore. + return; + } + NSMutableDictionary *otherClassMap = registry->mutableClassMap_; + [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) { +#pragma unused(stop) + Class containingMessageClass = key; + CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; + + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + [mutableClassMap_ objectForKey:containingMessageClass]; + if (extensionMap == nil) { + extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap); + [mutableClassMap_ setObject:(id)extensionMap + forKey:(id)containingMessageClass]; + CFRelease(extensionMap); + } else { + CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); + } + }]; +} + +#pragma clang diagnostic pop + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage.h new file mode 100644 index 0000000..276740d --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage.h @@ -0,0 +1,470 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBBootstrap.h" + +@class GPBDescriptor; +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionDescriptor; +@class GPBExtensionRegistry; +@class GPBFieldDescriptor; +@class GPBUnknownFieldSet; + +NS_ASSUME_NONNULL_BEGIN + +CF_EXTERN_C_BEGIN + +/** NSError domain used for errors. */ +extern NSString *const GPBMessageErrorDomain; + +/** Error codes for NSErrors originated in GPBMessage. */ +typedef NS_ENUM(NSInteger, GPBMessageErrorCode) { + /** Uncategorized error. */ + GPBMessageErrorCodeOther = -100, + /** Message couldn't be serialized because it is missing required fields. */ + GPBMessageErrorCodeMissingRequiredField = -101, +}; + +/** + * Key under which the GPBMessage error's reason is stored inside the userInfo + * dictionary. + **/ +extern NSString *const GPBErrorReasonKey; + +CF_EXTERN_C_END + +/** + * Base class that each generated message subclasses from. + * + * @note @c NSCopying support is a "deep copy", in that all sub objects are + * copied. Just like you wouldn't want a UIView/NSView trying to + * exist in two places, you don't want a sub message to be a property + * property of two other messages. + * + * @note While the class support NSSecureCoding, if the message has any + * extensions, they will end up reloaded in @c unknownFields as there is + * no way for the @c NSCoding plumbing to pass through a + * @c GPBExtensionRegistry. To support extensions, instead of passing the + * calls off to the Message, simple store the result of @c data, and then + * when loading, fetch the data and use + * @c +parseFromData:extensionRegistry:error: to provide an extension + * registry. + **/ +@interface GPBMessage : NSObject + +// If you add an instance method/property to this class that may conflict with +// fields declared in protos, you need to update objective_helpers.cc. The main +// cases are methods that take no arguments, or setFoo:/hasFoo: type methods. + +/** + * The set of unknown fields for this message. + * + * Only messages from proto files declared with "proto2" syntax support unknown + * fields. For "proto3" syntax, any unknown fields found while parsing are + * dropped. + **/ +@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields; + +/** + * Whether the message, along with all submessages, have the required fields + * set. This is only applicable for files declared with "proto2" syntax, as + * there are no required fields for "proto3" syntax. + **/ +@property(nonatomic, readonly, getter=isInitialized) BOOL initialized; + +/** + * @return An autoreleased message with the default values set. + **/ ++ (instancetype)message; + +/** + * Creates a new instance by parsing the provided data. This method should be + * sent to the generated message class that the data should be interpreted as. + * If there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param errorPtr An optional error pointer to fill in with a failure reason if + * the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr; + +/** + * Creates a new instance by parsing the data. This method should be sent to + * the generated message class that the data should be interpreted as. If + * there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseFromData:(NSData *)data + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Creates a new instance by parsing the data from the given input stream. This + * method should be sent to the generated message class that the data should + * be interpreted as. If there is an error the method returns nil and the error + * is returned in errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param input The stream to read data from. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Creates a new instance by parsing the data from the given input stream. This + * method should be sent to the generated message class that the data should + * be interpreted as. If there is an error the method returns nil and the error + * is returned in errorPtr (when provided). + * + * @note Unlike the parseFrom... methods, this never checks to see if all of + * the required fields are set. So this method can be used to reload + * messages that may not be complete. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param input The stream to read data from. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Initializes an instance by parsing the data. This method should be sent to + * the generated message class that the data should be interpreted as. If + * there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param errorPtr An optional error pointer to fill in with a failure reason if + * the data can not be parsed. + * + * @return An initialized instance of the generated class. + **/ +- (nullable instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr; + +/** + * Initializes an instance by parsing the data. This method should be sent to + * the generated message class that the data should be interpreted as. If + * there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return An initialized instance of the generated class. + **/ +- (nullable instancetype)initWithData:(NSData *)data + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Initializes an instance by parsing the data from the given input stream. This + * method should be sent to the generated message class that the data should + * be interpreted as. If there is an error the method returns nil and the error + * is returned in errorPtr (when provided). + * + * @note Unlike the parseFrom... methods, this never checks to see if all of + * the required fields are set. So this method can be used to reload + * messages that may not be complete. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param input The stream to read data from. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return An initialized instance of the generated class. + **/ +- (nullable instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Parses the given data as this message's class, and merges those values into + * this message. + * + * @param data The binary representation of the message to merge. + * @param extensionRegistry The extension registry to use to look up extensions. + * + * @exception GPBCodedInputStreamException Exception thrown when parsing was + * unsuccessful. + **/ +- (void)mergeFromData:(NSData *)data + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry; + +/** + * Merges the fields from another message (of the same type) into this + * message. + * + * @param other Message to merge into this message. + **/ +- (void)mergeFrom:(GPBMessage *)other; + +/** + * Writes out the message to the given coded output stream. + * + * @param output The coded output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + * + **/ +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output; + +/** + * Writes out the message to the given output stream. + * + * @param output The output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + **/ +- (void)writeToOutputStream:(NSOutputStream *)output; + +/** + * Writes out a varint for the message size followed by the the message to + * the given output stream. + * + * @param output The coded output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + **/ +- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output; + +/** + * Writes out a varint for the message size followed by the the message to + * the given output stream. + * + * @param output The output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + **/ +- (void)writeDelimitedToOutputStream:(NSOutputStream *)output; + +/** + * Serializes the message to an NSData. + * + * If there is an error while generating the data, nil is returned. + * + * @note This value is not cached, so if you are using it repeatedly, cache + * it yourself. + * + * @note In DEBUG ONLY, the message is also checked for all required field, + * if one is missing, nil will be returned. + * + * @return The binary representation of the message. + **/ +- (nullable NSData *)data; + +/** + * Serializes a varint with the message size followed by the message data, + * returning that as an NSData. + * + * @note This value is not cached, so if you are using it repeatedly, it is + * recommended to keep a local copy. + * + * @return The binary representation of the size along with the message. + **/ +- (NSData *)delimitedData; + +/** + * Calculates the size of the object if it were serialized. + * + * This is not a cached value. If you are following a pattern like this: + * + * ``` + * size_t size = [aMsg serializedSize]; + * NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; + * [foo writeSize:size]; + * [foo appendData:[aMsg data]]; + * ``` + * + * you would be better doing: + * + * ``` + * NSData *data = [aMsg data]; + * NSUInteger size = [aMsg length]; + * NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; + * [foo writeSize:size]; + * [foo appendData:data]; + * ``` + * + * @return The size of the message in it's binary representation. + **/ +- (size_t)serializedSize; + +/** + * @return The descriptor for the message class. + **/ ++ (GPBDescriptor *)descriptor; + +/** + * Return the descriptor for the message. + **/ +- (GPBDescriptor *)descriptor; + +/** + * @return An array with the extension descriptors that are currently set on the + * message. + **/ +- (NSArray *)extensionsCurrentlySet; + +/** + * Checks whether there is an extension set on the message which matches the + * given extension descriptor. + * + * @param extension Extension descriptor to check if it's set on the message. + * + * @return Whether the extension is currently set on the message. + **/ +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension; + +/* + * Fetches the given extension's value for this message. + * + * Extensions use boxed values (NSNumbers) for PODs and NSMutableArrays for + * repeated fields. If the extension is a Message one will be auto created for + * you and returned similar to fields. + * + * @param extension The extension descriptor of the extension to fetch. + * + * @return The extension matching the given descriptor, or nil if none found. + **/ +- (nullable id)getExtension:(GPBExtensionDescriptor *)extension; + +/** + * Sets the given extension's value for this message. This only applies for + * single field extensions (i.e. - not repeated fields). + * + * Extensions use boxed values (NSNumbers). + * + * @param extension The extension descriptor under which to set the value. + * @param value The value to be set as the extension. + **/ +- (void)setExtension:(GPBExtensionDescriptor *)extension + value:(nullable id)value; + +/** + * Adds the given value to the extension for this message. This only applies + * to repeated field extensions. If the field is a repeated POD type, the value + * should be an NSNumber. + * + * @param extension The extension descriptor under which to add the value. + * @param value The value to be added to the repeated extension. + **/ +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value; + +/** + * Replaces the value at the given index with the given value for the extension + * on this message. This only applies to repeated field extensions. If the field + * is a repeated POD type, the value is should be an NSNumber. + * + * @param extension The extension descriptor under which to replace the value. + * @param index The index of the extension to be replaced. + * @param value The value to be replaced in the repeated extension. + **/ +- (void)setExtension:(GPBExtensionDescriptor *)extension + index:(NSUInteger)index + value:(id)value; + +/** + * Clears the given extension for this message. + * + * @param extension The extension descriptor to be cleared from this message. + **/ +- (void)clearExtension:(GPBExtensionDescriptor *)extension; + +/** + * Resets all of the fields of this message to their default values. + **/ +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage.m new file mode 100644 index 0000000..3d5eccd --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage.m @@ -0,0 +1,3348 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBMessage_PackagePrivate.h" + +#import +#import +#import + +#import "GPBArray_PackagePrivate.h" +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary_PackagePrivate.h" +#import "GPBExtensionInternals.h" +#import "GPBExtensionRegistry.h" +#import "GPBRootObject_PackagePrivate.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +NSString *const GPBMessageErrorDomain = + GPBNSStringifySymbol(GPBMessageErrorDomain); + +NSString *const GPBErrorReasonKey = @"Reason"; + +static NSString *const kGPBDataCoderKey = @"GPBData"; + +// +// PLEASE REMEMBER: +// +// This is the base class for *all* messages generated, so any selector defined, +// *public* or *private* could end up colliding with a proto message field. So +// avoid using selectors that could match a property, use C functions to hide +// them, etc. +// + +@interface GPBMessage () { + @package + GPBUnknownFieldSet *unknownFields_; + NSMutableDictionary *extensionMap_; + NSMutableDictionary *autocreatedExtensionMap_; + + // If the object was autocreated, we remember the creator so that if we get + // mutated, we can inform the creator to make our field visible. + GPBMessage *autocreator_; + GPBFieldDescriptor *autocreatorField_; + GPBExtensionDescriptor *autocreatorExtension_; + + // A lock to provide mutual exclusion from internal data that can be modified + // by *read* operations such as getters (autocreation of message fields and + // message extensions, not setting of values). Used to guarantee thread safety + // for concurrent reads on the message. + // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have + // pointed out that they are vulnerable to live locking on iOS in cases of + // priority inversion: + // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ + // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html + // Use of readOnlySemaphore_ must be prefaced by a call to + // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows + // readOnlySemaphore_ to be only created when actually needed. + _Atomic(dispatch_semaphore_t) readOnlySemaphore_; +} +@end + +static id CreateArrayForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) + __attribute__((ns_returns_retained)); +static id GetOrCreateArrayIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax); +static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); +static id CreateMapForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) + __attribute__((ns_returns_retained)); +static id GetOrCreateMapIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax); +static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); +static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, + NSZone *zone) + __attribute__((ns_returns_retained)); + +#ifdef DEBUG +static NSError *MessageError(NSInteger code, NSDictionary *userInfo) { + return [NSError errorWithDomain:GPBMessageErrorDomain + code:code + userInfo:userInfo]; +} +#endif + +static NSError *ErrorFromException(NSException *exception) { + NSError *error = nil; + + if ([exception.name isEqual:GPBCodedInputStreamException]) { + NSDictionary *exceptionInfo = exception.userInfo; + error = exceptionInfo[GPBCodedInputStreamUnderlyingErrorKey]; + } + + if (!error) { + NSString *reason = exception.reason; + NSDictionary *userInfo = nil; + if ([reason length]) { + userInfo = @{ GPBErrorReasonKey : reason }; + } + + error = [NSError errorWithDomain:GPBMessageErrorDomain + code:GPBMessageErrorCodeOther + userInfo:userInfo]; + } + return error; +} + +static void CheckExtension(GPBMessage *self, + GPBExtensionDescriptor *extension) { + if (![self isKindOfClass:extension.containingMessageClass]) { + [NSException + raise:NSInvalidArgumentException + format:@"Extension %@ used on wrong class (%@ instead of %@)", + extension.singletonName, + [self class], extension.containingMessageClass]; + } +} + +static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, + NSZone *zone) { + if (extensionMap.count == 0) { + return nil; + } + NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone] + initWithCapacity:extensionMap.count]; + + for (GPBExtensionDescriptor *extension in extensionMap) { + id value = [extensionMap objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); + + if (extension.repeated) { + if (isMessageExtension) { + NSMutableArray *list = + [[NSMutableArray alloc] initWithCapacity:[value count]]; + for (GPBMessage *listValue in value) { + GPBMessage *copiedValue = [listValue copyWithZone:zone]; + [list addObject:copiedValue]; + [copiedValue release]; + } + [result setObject:list forKey:extension]; + [list release]; + } else { + NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; + [result setObject:copiedValue forKey:extension]; + [copiedValue release]; + } + } else { + if (isMessageExtension) { + GPBMessage *copiedValue = [value copyWithZone:zone]; + [result setObject:copiedValue forKey:extension]; + [copiedValue release]; + } else { + [result setObject:value forKey:extension]; + } + } + } + + return result; +} + +static id CreateArrayForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) { + id result; + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { + case GPBDataTypeBool: + result = [[GPBBoolArray alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBUInt32Array alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBInt32Array alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBUInt64Array alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBInt64Array alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBFloatArray alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBDoubleArray alloc] init]; + break; + + case GPBDataTypeEnum: + result = [[GPBEnumArray alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + case GPBDataTypeString: + if (autocreator) { + result = [[GPBAutocreatedArray alloc] init]; + } else { + result = [[NSMutableArray alloc] init]; + } + break; + } + + if (autocreator) { + if (GPBDataTypeIsObject(fieldDataType)) { + GPBAutocreatedArray *autoArray = result; + autoArray->_autocreator = autocreator; + } else { + GPBInt32Array *gpbArray = result; + gpbArray->_autocreator = autocreator; + } + } + + return result; +} + +static id CreateMapForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) { + id result; + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + switch (keyDataType) { + case GPBDataTypeBool: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBBoolBoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBBoolUInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBBoolInt32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBBoolUInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBBoolInt64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBBoolFloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBBoolDoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBBoolEnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBBoolObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBUInt32BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBUInt32UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBUInt32Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBUInt32UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBUInt32Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBUInt32FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBUInt32DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBUInt32EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBUInt32ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBInt32BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBInt32UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBInt32Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBInt32UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBInt32Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBInt32FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBInt32DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBInt32EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBInt32ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBUInt64BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBUInt64UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBUInt64Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBUInt64UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBUInt64Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBUInt64FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBUInt64DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBUInt64EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBUInt64ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBInt64BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBInt64UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBInt64Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBInt64UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBInt64Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBInt64FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBInt64DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBInt64EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBInt64ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeString: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBStringBoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBStringUInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBStringInt32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBStringUInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBStringInt64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBStringFloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBStringDoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBStringEnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + if (autocreator) { + result = [[GPBAutocreatedDictionary alloc] init]; + } else { + result = [[NSMutableDictionary alloc] init]; + } + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeEnum: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + + if (autocreator) { + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + GPBAutocreatedDictionary *autoDict = result; + autoDict->_autocreator = autocreator; + } else { + GPBInt32Int32Dictionary *gpbDict = result; + gpbDict->_autocreator = autocreator; + } + } + + return result; +} + +#if !defined(__clang_analyzer__) +// These functions are blocked from the analyzer because the analyzer sees the +// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map, +// so use of the array/map after the call returns is flagged as a use after +// free. +// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain +// count be holding onto the object (it is transfering it), the object is +// still valid after returning from the call. The other way to avoid this +// would be to add a -retain/-autorelease, but that would force every +// repeated/map field parsed into the autorelease pool which is both a memory +// and performance hit. + +static id GetOrCreateArrayIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax) { + id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!array) { + // No lock needed, this is called from places expecting to mutate + // so no threading protection is needed. + array = CreateArrayForField(field, nil); + GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax); + } + return array; +} + +// This is like GPBGetObjectIvarWithField(), but for arrays, it should +// only be used to wire the method into the class. +static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!array) { + // Check again after getting the lock. + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); + array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!array) { + array = CreateArrayForField(field, self); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); + } + dispatch_semaphore_signal(self->readOnlySemaphore_); + } + return array; +} + +static id GetOrCreateMapIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax) { + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + // No lock needed, this is called from places expecting to mutate + // so no threading protection is needed. + dict = CreateMapForField(field, nil); + GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); + } + return dict; +} + +// This is like GPBGetObjectIvarWithField(), but for maps, it should +// only be used to wire the method into the class. +static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + // Check again after getting the lock. + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); + dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + dict = CreateMapForField(field, self); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); + } + dispatch_semaphore_signal(self->readOnlySemaphore_); + } + return dict; +} + +#endif // !defined(__clang_analyzer__) + +GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, + GPBMessage *autocreator, + GPBFieldDescriptor *field) { + GPBMessage *message = [[msgClass alloc] init]; + message->autocreator_ = autocreator; + message->autocreatorField_ = [field retain]; + return message; +} + +static GPBMessage *CreateMessageWithAutocreatorForExtension( + Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension) + __attribute__((ns_returns_retained)); + +static GPBMessage *CreateMessageWithAutocreatorForExtension( + Class msgClass, GPBMessage *autocreator, + GPBExtensionDescriptor *extension) { + GPBMessage *message = [[msgClass alloc] init]; + message->autocreator_ = autocreator; + message->autocreatorExtension_ = [extension retain]; + return message; +} + +BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) { + return (message->autocreator_ == parent); +} + +void GPBBecomeVisibleToAutocreator(GPBMessage *self) { + // Message objects that are implicitly created by accessing a message field + // are initially not visible via the hasX selector. This method makes them + // visible. + if (self->autocreator_) { + // This will recursively make all parent messages visible until it reaches a + // super-creator that's visible. + if (self->autocreatorField_) { + GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax; + GPBSetObjectIvarWithFieldInternal(self->autocreator_, + self->autocreatorField_, self, syntax); + } else { + [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; + } + } +} + +void GPBAutocreatedArrayModified(GPBMessage *self, id array) { + // When one of our autocreated arrays adds elements, make it visible. + GPBDescriptor *descriptor = [[self class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.fieldType == GPBFieldTypeRepeated) { + id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (curArray == array) { + if (GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedArray *autoArray = array; + autoArray->_autocreator = nil; + } else { + GPBInt32Array *gpbArray = array; + gpbArray->_autocreator = nil; + } + GPBBecomeVisibleToAutocreator(self); + return; + } + } + } + NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self); +} + +void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { + // When one of our autocreated dicts adds elements, make it visible. + GPBDescriptor *descriptor = [[self class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.fieldType == GPBFieldTypeMap) { + id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (curDict == dictionary) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedDictionary *autoDict = dictionary; + autoDict->_autocreator = nil; + } else { + GPBInt32Int32Dictionary *gpbDict = dictionary; + gpbDict->_autocreator = nil; + } + GPBBecomeVisibleToAutocreator(self); + return; + } + } + } + NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self); +} + +void GPBClearMessageAutocreator(GPBMessage *self) { + if ((self == nil) || !self->autocreator_) { + return; + } + +#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) + // Either the autocreator must have its "has" flag set to YES, or it must be + // NO and not equal to ourselves. + BOOL autocreatorHas = + (self->autocreatorField_ + ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_) + : [self->autocreator_ hasExtension:self->autocreatorExtension_]); + GPBMessage *autocreatorFieldValue = + (self->autocreatorField_ + ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, + self->autocreatorField_) + : [self->autocreator_->autocreatedExtensionMap_ + objectForKey:self->autocreatorExtension_]); + NSCAssert(autocreatorHas || autocreatorFieldValue != self, + @"Cannot clear autocreator because it still refers to self, self: %@.", + self); + +#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) + + self->autocreator_ = nil; + [self->autocreatorField_ release]; + self->autocreatorField_ = nil; + [self->autocreatorExtension_ release]; + self->autocreatorExtension_ = nil; +} + +// Call this before using the readOnlySemaphore_. This ensures it is created only once. +void GPBPrepareReadOnlySemaphore(GPBMessage *self) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + + // Create the semaphore on demand (rather than init) as developers might not cause them + // to be needed, and the heap usage can add up. The atomic swap is used to avoid needing + // another lock around creating it. + if (self->readOnlySemaphore_ == nil) { + dispatch_semaphore_t worker = dispatch_semaphore_create(1); + dispatch_semaphore_t expected = nil; + if (!atomic_compare_exchange_strong(&self->readOnlySemaphore_, &expected, worker)) { + dispatch_release(worker); + } +#if defined(__clang_analyzer__) + // The Xcode 9.2 (and 9.3 beta) static analyzer thinks worker is leaked + // (doesn't seem to know about atomic_compare_exchange_strong); so just + // for the analyzer, let it think worker is also released in this case. + else { dispatch_release(worker); } +#endif + } + +#pragma clang diagnostic pop +} + +static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { + if (!self->unknownFields_) { + self->unknownFields_ = [[GPBUnknownFieldSet alloc] init]; + GPBBecomeVisibleToAutocreator(self); + } + return self->unknownFields_; +} + +@implementation GPBMessage + ++ (void)initialize { + Class pbMessageClass = [GPBMessage class]; + if ([self class] == pbMessageClass) { + // This is here to start up the "base" class descriptor. + [self descriptor]; + // Message shares extension method resolving with GPBRootObject so insure + // it is started up at the same time. + (void)[GPBRootObject class]; + } else if ([self superclass] == pbMessageClass) { + // This is here to start up all the "message" subclasses. Just needs to be + // done for the messages, not any of the subclasses. + // This must be done in initialize to enforce thread safety of start up of + // the protocol buffer library. + // Note: The generated code for -descriptor calls + // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject + // subclass for the file. That call chain is what ensures that *Root class + // is started up to support extension resolution off the message class + // (+resolveClassMethod: below) in a thread safe manner. + [self descriptor]; + } +} + ++ (instancetype)allocWithZone:(NSZone *)zone { + // Override alloc to allocate our classes with the additional storage + // required for the instance variables. + GPBDescriptor *descriptor = [self descriptor]; + return NSAllocateObject(self, descriptor->storageSize_, zone); +} + ++ (instancetype)alloc { + return [self allocWithZone:nil]; +} + ++ (GPBDescriptor *)descriptor { + // This is thread safe because it is called from +initialize. + static GPBDescriptor *descriptor = NULL; + static GPBFileDescriptor *fileDescriptor = NULL; + if (!descriptor) { + // Use a dummy file that marks it as proto2 syntax so when used generically + // it supports unknowns/etc. + fileDescriptor = + [[GPBFileDescriptor alloc] initWithPackage:@"internal" + syntax:GPBFileSyntaxProto2]; + + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] + rootClass:Nil + file:fileDescriptor + fields:NULL + fieldCount:0 + storageSize:0 + flags:0]; + } + return descriptor; +} + ++ (instancetype)message { + return [[[self alloc] init] autorelease]; +} + +- (instancetype)init { + if ((self = [super init])) { + messageStorage_ = (GPBMessage_StoragePtr)( + ((uint8_t *)self) + class_getInstanceSize([self class])); + } + + return self; +} + +- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { + return [self initWithData:data extensionRegistry:nil error:errorPtr]; +} + +- (instancetype)initWithData:(NSData *)data + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + if ((self = [self init])) { + @try { + [self mergeFromData:data extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } + } + @catch (NSException *exception) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = ErrorFromException(exception); + } + } +#ifdef DEBUG + if (self && !self.initialized) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif + } + return self; +} + +- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + if ((self = [self init])) { + @try { + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } + } + @catch (NSException *exception) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = ErrorFromException(exception); + } + } +#ifdef DEBUG + if (self && !self.initialized) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif + } + return self; +} + +- (void)dealloc { + [self internalClear:NO]; + NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); + if (readOnlySemaphore_) { + dispatch_release(readOnlySemaphore_); + } + [super dealloc]; +} + +- (void)copyFieldsInto:(GPBMessage *)message + zone:(NSZone *)zone + descriptor:(GPBDescriptor *)descriptor { + // Copy all the storage... + memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); + + GPBFileSyntax syntax = descriptor.file.syntax; + + // Loop over the fields doing fixup... + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (value) { + // We need to copy the array/map, but the catch is for message fields, + // we also need to ensure all the messages as those need copying also. + id newValue; + if (GPBFieldDataTypeIsMessage(field)) { + if (field.fieldType == GPBFieldTypeRepeated) { + NSArray *existingArray = (NSArray *)value; + NSMutableArray *newArray = + [[NSMutableArray alloc] initWithCapacity:existingArray.count]; + newValue = newArray; + for (GPBMessage *msg in existingArray) { + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [newArray addObject:copiedMsg]; + [copiedMsg release]; + } + } else { + if (field.mapKeyDataType == GPBDataTypeString) { + // Map is an NSDictionary. + NSDictionary *existingDict = value; + NSMutableDictionary *newDict = [[NSMutableDictionary alloc] + initWithCapacity:existingDict.count]; + newValue = newDict; + [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, + GPBMessage *msg, + BOOL *stop) { +#pragma unused(stop) + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [newDict setObject:copiedMsg forKey:key]; + [copiedMsg release]; + }]; + } else { + // Is one of the GPB*ObjectDictionary classes. Type doesn't + // matter, just need one to invoke the selector. + GPBInt32ObjectDictionary *existingDict = value; + newValue = [existingDict deepCopyWithZone:zone]; + } + } + } else { + // Not messages (but is a map/array)... + if (field.fieldType == GPBFieldTypeRepeated) { + if (GPBFieldDataTypeIsObject(field)) { + // NSArray + newValue = [value mutableCopyWithZone:zone]; + } else { + // GPB*Array + newValue = [value copyWithZone:zone]; + } + } else { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + // NSDictionary + newValue = [value mutableCopyWithZone:zone]; + } else { + // Is one of the GPB*Dictionary classes. Type doesn't matter, + // just need one to invoke the selector. + GPBInt32Int32Dictionary *existingDict = value; + newValue = [existingDict copyWithZone:zone]; + } + } + } + // We retain here because the memcpy picked up the pointer value and + // the next call to SetRetainedObject... will release the current value. + [value retain]; + GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, + syntax); + } + } else if (GPBFieldDataTypeIsMessage(field)) { + // For object types, if we have a value, copy it. If we don't, + // zero it to remove the pointer to something that was autocreated + // (and the ptr just got memcpyed). + if (GPBGetHasIvarField(self, field)) { + GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBMessage *newValue = [value copyWithZone:zone]; + // We retain here because the memcpy picked up the pointer value and + // the next call to SetRetainedObject... will release the current value. + [value retain]; + GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, + syntax); + } else { + uint8_t *storage = (uint8_t *)message->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + *typePtr = NULL; + } + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { + // A set string/data value (message picked off above), copy it. + id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + id newValue = [value copyWithZone:zone]; + // We retain here because the memcpy picked up the pointer value and + // the next call to SetRetainedObject... will release the current value. + [value retain]; + GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, + syntax); + } else { + // memcpy took care of the rest of the primitive fields if they were set. + } + } // for (field in descriptor->fields_) +} + +- (id)copyWithZone:(NSZone *)zone { + GPBDescriptor *descriptor = [self descriptor]; + GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init]; + + [self copyFieldsInto:result zone:zone descriptor:descriptor]; + // Make immutable copies of the extra bits. + result->unknownFields_ = [unknownFields_ copyWithZone:zone]; + result->extensionMap_ = CloneExtensionMap(extensionMap_, zone); + return result; +} + +- (void)clear { + [self internalClear:YES]; +} + +- (void)internalClear:(BOOL)zeroStorage { + GPBDescriptor *descriptor = [self descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (arrayOrMap) { + if (field.fieldType == GPBFieldTypeRepeated) { + if (GPBFieldDataTypeIsObject(field)) { + if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) { + GPBAutocreatedArray *autoArray = arrayOrMap; + if (autoArray->_autocreator == self) { + autoArray->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Array. + GPBInt32Array *gpbArray = arrayOrMap; + if (gpbArray->_autocreator == self) { + gpbArray->_autocreator = nil; + } + } + } else { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) { + GPBAutocreatedDictionary *autoDict = arrayOrMap; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Dictionary. + GPBInt32Int32Dictionary *gpbDict = arrayOrMap; + if (gpbDict->_autocreator == self) { + gpbDict->_autocreator = nil; + } + } + } + [arrayOrMap release]; + } + } else if (GPBFieldDataTypeIsMessage(field)) { + GPBClearAutocreatedMessageIvarWithField(self, field); + GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [value release]; + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { + id value = GPBGetObjectIvarWithField(self, field); + [value release]; + } + } + + // GPBClearMessageAutocreator() expects that its caller has already been + // removed from autocreatedExtensionMap_ so we set to nil first. + NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues]; + [autocreatedExtensionMap_ release]; + autocreatedExtensionMap_ = nil; + + // Since we're clearing all of our extensions, make sure that we clear the + // autocreator on any that we've created so they no longer refer to us. + for (GPBMessage *value in autocreatedValues) { + NSCAssert(GPBWasMessageAutocreatedBy(value, self), + @"Autocreated extension does not refer back to self."); + GPBClearMessageAutocreator(value); + } + + [extensionMap_ release]; + extensionMap_ = nil; + [unknownFields_ release]; + unknownFields_ = nil; + + // Note that clearing does not affect autocreator_. If we are being cleared + // because of a dealloc, then autocreator_ should be nil anyway. If we are + // being cleared because someone explicitly clears us, we don't want to + // sever our relationship with our autocreator. + + if (zeroStorage) { + memset(messageStorage_, 0, descriptor->storageSize_); + } +} + +- (BOOL)isInitialized { + GPBDescriptor *descriptor = [self descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.isRequired) { + if (!GPBGetHasIvarField(self, field)) { + return NO; + } + } + if (GPBFieldDataTypeIsMessage(field)) { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + if (field.isRequired) { + GPBMessage *message = GPBGetMessageMessageField(self, field); + if (!message.initialized) { + return NO; + } + } else { + NSAssert(field.isOptional, + @"%@: Single message field %@ not required or optional?", + [self class], field.name); + if (GPBGetHasIvarField(self, field)) { + GPBMessage *message = GPBGetMessageMessageField(self, field); + if (!message.initialized) { + return NO; + } + } + } + } else if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + for (GPBMessage *message in array) { + if (!message.initialized) { + return NO; + } + } + } else { // fieldType == GPBFieldTypeMap + if (field.mapKeyDataType == GPBDataTypeString) { + NSDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { + return NO; + } + } else { + // Real type is GPB*ObjectDictionary, exact type doesn't matter. + GPBInt32ObjectDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (map && ![map isInitialized]) { + return NO; + } + } + } + } + } + + __block BOOL result = YES; + [extensionMap_ + enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, + id obj, + BOOL *stop) { + if (GPBExtensionIsMessage(extension)) { + if (extension.isRepeated) { + for (GPBMessage *msg in obj) { + if (!msg.initialized) { + result = NO; + *stop = YES; + break; + } + } + } else { + GPBMessage *asMsg = obj; + if (!asMsg.initialized) { + result = NO; + *stop = YES; + } + } + } + }]; + return result; +} + +- (GPBDescriptor *)descriptor { + return [[self class] descriptor]; +} + +- (NSData *)data { +#ifdef DEBUG + if (!self.initialized) { + return nil; + } +#endif + NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]]; + GPBCodedOutputStream *stream = + [[GPBCodedOutputStream alloc] initWithData:data]; + @try { + [self writeToCodedOutputStream:stream]; + } + @catch (NSException *exception) { + // This really shouldn't happen. The only way writeToCodedOutputStream: + // could throw is if something in the library has a bug and the + // serializedSize was wrong. +#ifdef DEBUG + NSLog(@"%@: Internal exception while building message data: %@", + [self class], exception); +#endif + data = nil; + } + [stream release]; + return data; +} + +- (NSData *)delimitedData { + size_t serializedSize = [self serializedSize]; + size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize); + NSMutableData *data = + [NSMutableData dataWithLength:(serializedSize + varintSize)]; + GPBCodedOutputStream *stream = + [[GPBCodedOutputStream alloc] initWithData:data]; + @try { + [self writeDelimitedToCodedOutputStream:stream]; + } + @catch (NSException *exception) { + // This really shouldn't happen. The only way writeToCodedOutputStream: + // could throw is if something in the library has a bug and the + // serializedSize was wrong. +#ifdef DEBUG + NSLog(@"%@: Internal exception while building message delimitedData: %@", + [self class], exception); +#endif + // If it happens, truncate. + data.length = 0; + } + [stream release]; + return data; +} + +- (void)writeToOutputStream:(NSOutputStream *)output { + GPBCodedOutputStream *stream = + [[GPBCodedOutputStream alloc] initWithOutputStream:output]; + [self writeToCodedOutputStream:stream]; + [stream release]; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { + GPBDescriptor *descriptor = [self descriptor]; + NSArray *fieldsArray = descriptor->fields_; + NSUInteger fieldCount = fieldsArray.count; + const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; + NSUInteger extensionRangesCount = descriptor.extensionRangesCount; + NSArray *sortedExtensions = + [[extensionMap_ allKeys] sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; + for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { + if (i == fieldCount) { + [self writeExtensionsToCodedOutputStream:output + range:extensionRanges[j++] + sortedExtensions:sortedExtensions]; + } else if (j == extensionRangesCount || + GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { + [self writeField:fieldsArray[i++] toCodedOutputStream:output]; + } else { + [self writeExtensionsToCodedOutputStream:output + range:extensionRanges[j++] + sortedExtensions:sortedExtensions]; + } + } + if (descriptor.isWireFormat) { + [unknownFields_ writeAsMessageSetTo:output]; + } else { + [unknownFields_ writeToCodedOutputStream:output]; + } +} + +- (void)writeDelimitedToOutputStream:(NSOutputStream *)output { + GPBCodedOutputStream *codedOutput = + [[GPBCodedOutputStream alloc] initWithOutputStream:output]; + [self writeDelimitedToCodedOutputStream:codedOutput]; + [codedOutput release]; +} + +- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output { + [output writeRawVarintSizeTAs32:[self serializedSize]]; + [self writeToCodedOutputStream:output]; +} + +- (void)writeField:(GPBFieldDescriptor *)field + toCodedOutputStream:(GPBCodedOutputStream *)output { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + BOOL has = GPBGetHasIvarField(self, field); + if (!has) { + return; + } + } + uint32_t fieldNumber = GPBFieldNumber(field); + +//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE) +//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE) +//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE) +//% case GPBDataType##TYPE: +//% if (fieldType == GPBFieldTypeRepeated) { +//% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; +//% GPB##ARRAY_TYPE##Array *array = +//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% [output write##TYPE##Array:fieldNumber values:array tag:tag]; +//% } else if (fieldType == GPBFieldTypeSingle) { +//% [output write##TYPE:fieldNumber +//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; +//% } else { // fieldType == GPBFieldTypeMap +//% // Exact type here doesn't matter. +//% GPBInt32##ARRAY_TYPE##Dictionary *dict = +//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% [dict writeToCodedOutputStream:output asField:field]; +//% } +//% break; +//% +//%PDDM-DEFINE FIELD_CASE2(TYPE) +//% case GPBDataType##TYPE: +//% if (fieldType == GPBFieldTypeRepeated) { +//% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% [output write##TYPE##Array:fieldNumber values:array]; +//% } else if (fieldType == GPBFieldTypeSingle) { +//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check +//% // again. +//% [output write##TYPE:fieldNumber +//% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; +//% } else { // fieldType == GPBFieldTypeMap +//% // Exact type here doesn't matter. +//% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% GPBDataType mapKeyDataType = field.mapKeyDataType; +//% if (mapKeyDataType == GPBDataTypeString) { +//% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); +//% } else { +//% [dict writeToCodedOutputStream:output asField:field]; +//% } +//% } +//% break; +//% + + switch (GPBGetFieldDataType(field)) { + +//%PDDM-EXPAND FIELD_CASE(Bool, Bool) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeBool: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBBoolArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeBoolArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeBool:fieldNumber + value:GPBGetMessageBoolField(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32BoolDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeFixed32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeFixed32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeFixed32:fieldNumber + value:GPBGetMessageUInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSFixed32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSFixed32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSFixed32:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Float, Float) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeFloat: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBFloatArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeFloatArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeFloat:fieldNumber + value:GPBGetMessageFloatField(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32FloatDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeFixed64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeFixed64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeFixed64:fieldNumber + value:GPBGetMessageUInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSFixed64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSFixed64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSFixed64:fieldNumber + value:GPBGetMessageInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Double, Double) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeDouble: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBDoubleArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeDoubleArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeDouble:fieldNumber + value:GPBGetMessageDoubleField(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32DoubleDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Int32, Int32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeInt32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeInt32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeInt32:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Int64, Int64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeInt64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeInt64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeInt64:fieldNumber + value:GPBGetMessageInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SInt32, Int32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSInt32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSInt32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSInt32:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SInt64, Int64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSInt64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSInt64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSInt64:fieldNumber + value:GPBGetMessageInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeUInt32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeUInt32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeUInt32:fieldNumber + value:GPBGetMessageUInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeUInt64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeUInt64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeUInt64:fieldNumber + value:GPBGetMessageUInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeEnum: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBEnumArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeEnumArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeEnum:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32EnumDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE2(Bytes) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeBytes: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeBytesArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeBytes:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND FIELD_CASE2(String) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeString: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeStringArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeString:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND FIELD_CASE2(Message) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeMessage: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeMessageArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeMessage:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND FIELD_CASE2(Group) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeGroup: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeGroupArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeGroup:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND-END (18 expansions) + } +} + +#pragma mark - Extensions + +- (id)getExtension:(GPBExtensionDescriptor *)extension { + CheckExtension(self, extension); + id value = [extensionMap_ objectForKey:extension]; + if (value != nil) { + return value; + } + + // No default for repeated. + if (extension.isRepeated) { + return nil; + } + // Non messages get their default. + if (!GPBExtensionIsMessage(extension)) { + return extension.defaultValue; + } + + // Check for an autocreated value. + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); + value = [autocreatedExtensionMap_ objectForKey:extension]; + if (!value) { + // Auto create the message extensions to match normal fields. + value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, + extension); + + if (autocreatedExtensionMap_ == nil) { + autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; + } + + // We can't simply call setExtension here because that would clear the new + // value's autocreator. + [autocreatedExtensionMap_ setObject:value forKey:extension]; + [value release]; + } + + dispatch_semaphore_signal(readOnlySemaphore_); + return value; +} + +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension { + // This is an internal method so we don't need to call CheckExtension(). + return [extensionMap_ objectForKey:extension]; +} + +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { +#if defined(DEBUG) && DEBUG + CheckExtension(self, extension); +#endif // DEBUG + return nil != [extensionMap_ objectForKey:extension]; +} + +- (NSArray *)extensionsCurrentlySet { + return [extensionMap_ allKeys]; +} + +- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output + range:(GPBExtensionRange)range + sortedExtensions:(NSArray *)sortedExtensions { + uint32_t start = range.start; + uint32_t end = range.end; + for (GPBExtensionDescriptor *extension in sortedExtensions) { + uint32_t fieldNumber = extension.fieldNumber; + if (fieldNumber < start) { + continue; + } + if (fieldNumber >= end) { + break; + } + id value = [extensionMap_ objectForKey:extension]; + GPBWriteExtensionValueToOutputStream(extension, value, output); + } +} + +- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { + if (!value) { + [self clearExtension:extension]; + return; + } + + CheckExtension(self, extension); + + if (extension.repeated) { + [NSException raise:NSInvalidArgumentException + format:@"Must call addExtension() for repeated types."]; + } + + if (extensionMap_ == nil) { + extensionMap_ = [[NSMutableDictionary alloc] init]; + } + + // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION. + // Without it, the compiler complains we're passing an id nullable when + // setObject:forKey: requires a id nonnull for the value. The check for + // !value at the start of the method ensures it isn't nil, but the check + // isn't smart enough to realize that. + [extensionMap_ setObject:(id)value forKey:extension]; + + GPBExtensionDescriptor *descriptor = extension; + + if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { + GPBMessage *autocreatedValue = + [[autocreatedExtensionMap_ objectForKey:extension] retain]; + // Must remove from the map before calling GPBClearMessageAutocreator() so + // that GPBClearMessageAutocreator() knows its safe to clear. + [autocreatedExtensionMap_ removeObjectForKey:extension]; + GPBClearMessageAutocreator(autocreatedValue); + [autocreatedValue release]; + } + + GPBBecomeVisibleToAutocreator(self); +} + +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { + CheckExtension(self, extension); + + if (!extension.repeated) { + [NSException raise:NSInvalidArgumentException + format:@"Must call setExtension() for singular types."]; + } + + if (extensionMap_ == nil) { + extensionMap_ = [[NSMutableDictionary alloc] init]; + } + NSMutableArray *list = [extensionMap_ objectForKey:extension]; + if (list == nil) { + list = [NSMutableArray array]; + [extensionMap_ setObject:list forKey:extension]; + } + + [list addObject:value]; + GPBBecomeVisibleToAutocreator(self); +} + +- (void)setExtension:(GPBExtensionDescriptor *)extension + index:(NSUInteger)idx + value:(id)value { + CheckExtension(self, extension); + + if (!extension.repeated) { + [NSException raise:NSInvalidArgumentException + format:@"Must call setExtension() for singular types."]; + } + + if (extensionMap_ == nil) { + extensionMap_ = [[NSMutableDictionary alloc] init]; + } + + NSMutableArray *list = [extensionMap_ objectForKey:extension]; + + [list replaceObjectAtIndex:idx withObject:value]; + GPBBecomeVisibleToAutocreator(self); +} + +- (void)clearExtension:(GPBExtensionDescriptor *)extension { + CheckExtension(self, extension); + + // Only become visible if there was actually a value to clear. + if ([extensionMap_ objectForKey:extension]) { + [extensionMap_ removeObjectForKey:extension]; + GPBBecomeVisibleToAutocreator(self); + } +} + +#pragma mark - mergeFrom + +- (void)mergeFromData:(NSData *)data + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + [input checkLastTagWas:0]; + [input release]; +} + +#pragma mark - mergeDelimitedFrom + +- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + GPBCodedInputStreamState *state = &input->state_; + if (GPBCodedInputStreamIsAtEnd(state)) { + return; + } + NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); + if (data == nil) { + return; + } + [self mergeFromData:data extensionRegistry:extensionRegistry]; + [data release]; +} + +#pragma mark - Parse From Data Support + ++ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr { + return [self parseFromData:data extensionRegistry:nil error:errorPtr]; +} + ++ (instancetype)parseFromData:(NSData *)data + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + return [[[self alloc] initWithData:data + extensionRegistry:extensionRegistry + error:errorPtr] autorelease]; +} + ++ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + return + [[[self alloc] initWithCodedInputStream:input + extensionRegistry:extensionRegistry + error:errorPtr] autorelease]; +} + +#pragma mark - Parse Delimited From Data Support + ++ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + GPBMessage *message = [[[self alloc] init] autorelease]; + @try { + [message mergeDelimitedFromCodedInputStream:input + extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } + } + @catch (NSException *exception) { + message = nil; + if (errorPtr) { + *errorPtr = ErrorFromException(exception); + } + } +#ifdef DEBUG + if (message && !message.initialized) { + message = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif + return message; +} + +#pragma mark - Unknown Field Support + +- (GPBUnknownFieldSet *)unknownFields { + return unknownFields_; +} + +- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields { + if (unknownFields != unknownFields_) { + [unknownFields_ release]; + unknownFields_ = [unknownFields copy]; + GPBBecomeVisibleToAutocreator(self); + } +} + +- (void)parseMessageSet:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + uint32_t typeId = 0; + NSData *rawBytes = nil; + GPBExtensionDescriptor *extension = nil; + GPBCodedInputStreamState *state = &input->state_; + while (true) { + uint32_t tag = GPBCodedInputStreamReadTag(state); + if (tag == 0) { + break; + } + + if (tag == GPBWireFormatMessageSetTypeIdTag) { + typeId = GPBCodedInputStreamReadUInt32(state); + if (typeId != 0) { + extension = [extensionRegistry extensionForDescriptor:[self descriptor] + fieldNumber:typeId]; + } + } else if (tag == GPBWireFormatMessageSetMessageTag) { + rawBytes = + [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; + } else { + if (![input skipField:tag]) { + break; + } + } + } + + [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag]; + + if (rawBytes != nil && typeId != 0) { + if (extension != nil) { + GPBCodedInputStream *newInput = + [[GPBCodedInputStream alloc] initWithData:rawBytes]; + GPBExtensionMergeFromInputStream(extension, + extension.packable, + newInput, + extensionRegistry, + self); + [newInput release]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + // rawBytes was created via a NoCopy, so it can be reusing a + // subrange of another NSData that might go out of scope as things + // unwind, so a copy is needed to ensure what is saved in the + // unknown fields stays valid. + NSData *cloned = [NSData dataWithData:rawBytes]; + [unknownFields mergeMessageSetMessage:typeId data:cloned]; + } + } +} + +- (BOOL)parseUnknownField:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + tag:(uint32_t)tag { + GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); + int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); + + GPBDescriptor *descriptor = [self descriptor]; + GPBExtensionDescriptor *extension = + [extensionRegistry extensionForDescriptor:descriptor + fieldNumber:fieldNumber]; + if (extension == nil) { + if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) { + [self parseMessageSet:input extensionRegistry:extensionRegistry]; + return YES; + } + } else { + if (extension.wireType == wireType) { + GPBExtensionMergeFromInputStream(extension, + extension.packable, + input, + extensionRegistry, + self); + return YES; + } + // Primitive, repeated types can be packed on unpacked on the wire, and are + // parsed either way. + if ([extension isRepeated] && + !GPBDataTypeIsObject(extension->description_->dataType) && + (extension.alternateWireType == wireType)) { + GPBExtensionMergeFromInputStream(extension, + !extension.packable, + input, + extensionRegistry, + self); + return YES; + } + } + if ([GPBUnknownFieldSet isFieldTag:tag]) { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + return [unknownFields mergeFieldFrom:tag input:input]; + } else { + return NO; + } +} + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields addUnknownMapEntry:fieldNum value:data]; +} + +#pragma mark - MergeFromCodedInputStream Support + +static void MergeSingleFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ + GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ + GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + + case GPBDataTypeMessage: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readMessage:message extensionRegistry:extensionRegistry]; + } else { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + } + break; + } + + case GPBDataTypeGroup: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + } else { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + } + break; + } + + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(&input->state_); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + } + } // switch +} + +static void MergeRepeatedPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + switch (fieldDataType) { +#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } + CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Float, float, Float) + CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(Double, double, Double) + CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) +#undef CASE_REPEATED_PACKED_POD + + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + NSCAssert(NO, @"Non primitive types can't be packed"); + break; + + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + break; + } + } // switch + } // while(BytesUntilLimit() > 0) + GPBCodedInputStreamPopLimit(state, limit); +} + +static void MergeRepeatedNotPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + switch (GPBGetFieldDataType(field)) { +#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } +#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(state); \ + [(NSMutableArray*)genericArray addObject:val]; \ + [val release]; \ + break; \ + } + CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) + CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) + CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) + CASE_REPEATED_NOT_PACKED_OBJECT(String) +#undef CASE_REPEATED_NOT_PACKED_POD +#undef CASE_NOT_PACKED_OBJECT + case GPBDataTypeMessage: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; + } + case GPBDataTypeGroup: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; + } + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + break; + } + } // switch +} + +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + GPBDescriptor *descriptor = [self descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + GPBCodedInputStreamState *state = &input->state_; + uint32_t tag = 0; + NSUInteger startingIndex = 0; + NSArray *fields = descriptor->fields_; + NSUInteger numFields = fields.count; + while (YES) { + BOOL merged = NO; + tag = GPBCodedInputStreamReadTag(state); + if (tag == 0) { + break; // Reached end. + } + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if (GPBFieldTag(fieldDescriptor) == tag) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + if (fieldType == GPBFieldTypeSingle) { + MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax, + input, extensionRegistry); + // Well formed protos will only have a single field once, advance + // the starting index to the next field. + startingIndex += 1; + } else if (fieldType == GPBFieldTypeRepeated) { + if (fieldDescriptor.isPackable) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + } else { // fieldType == GPBFieldTypeMap + // GPB*Dictionary or NSDictionary, exact type doesn't matter at this + // point. + id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); + [input readMapEntry:map + extensionRegistry:extensionRegistry + field:fieldDescriptor + parentMessage:self]; + } + merged = YES; + break; + } else { + startingIndex += 1; + } + } // for(i < numFields) + + if (!merged && (tag != 0)) { + // Primitive, repeated types can be packed on unpacked on the wire, and + // are parsed either way. The above loop covered tag in the preferred + // for, so this need to check the alternate form. + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && + !GPBFieldDataTypeIsObject(fieldDescriptor) && + (GPBFieldAlternateTag(fieldDescriptor) == tag)) { + BOOL alternateIsPacked = !fieldDescriptor.isPackable; + if (alternateIsPacked) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + merged = YES; + break; + } else { + startingIndex += 1; + } + } + } + + if (!merged) { + if (tag == 0) { + // zero signals EOF / limit reached + return; + } else { + if (![self parseUnknownField:input + extensionRegistry:extensionRegistry + tag:tag]) { + // it's an endgroup tag + return; + } + } + } // if(!merged) + + } // while(YES) +} + +#pragma mark - MergeFrom Support + +- (void)mergeFrom:(GPBMessage *)other { + Class selfClass = [self class]; + Class otherClass = [other class]; + if (!([selfClass isSubclassOfClass:otherClass] || + [otherClass isSubclassOfClass:selfClass])) { + [NSException raise:NSInvalidArgumentException + format:@"Classes must match %@ != %@", selfClass, otherClass]; + } + + // We assume something will be done and become visible. + GPBBecomeVisibleToAutocreator(self); + + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNumber = GPBFieldNumber(field); + if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { + // Other doesn't have the field set, on to the next. + continue; + } + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { + case GPBDataTypeBool: + GPBSetBoolIvarWithFieldInternal( + self, field, GPBGetMessageBoolField(other, field), syntax); + break; + case GPBDataTypeSFixed32: + case GPBDataTypeEnum: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + GPBSetInt32IvarWithFieldInternal( + self, field, GPBGetMessageInt32Field(other, field), syntax); + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + GPBSetUInt32IvarWithFieldInternal( + self, field, GPBGetMessageUInt32Field(other, field), syntax); + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + GPBSetInt64IvarWithFieldInternal( + self, field, GPBGetMessageInt64Field(other, field), syntax); + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + GPBSetUInt64IvarWithFieldInternal( + self, field, GPBGetMessageUInt64Field(other, field), syntax); + break; + case GPBDataTypeFloat: + GPBSetFloatIvarWithFieldInternal( + self, field, GPBGetMessageFloatField(other, field), syntax); + break; + case GPBDataTypeDouble: + GPBSetDoubleIvarWithFieldInternal( + self, field, GPBGetMessageDoubleField(other, field), syntax); + break; + case GPBDataTypeBytes: + case GPBDataTypeString: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); + break; + } + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [message mergeFrom:otherVal]; + } else { + GPBMessage *message = [otherVal copy]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, + syntax); + } + break; + } + } // switch() + } else if (fieldType == GPBFieldTypeRepeated) { + // In the case of a list, they need to be appended, and there is no + // _hasIvar to worry about setting. + id otherArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (otherArray) { + GPBDataType fieldDataType = field->description_->dataType; + if (GPBDataTypeIsObject(fieldDataType)) { + NSMutableArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addObjectsFromArray:otherArray]; + } else if (fieldDataType == GPBDataTypeEnum) { + GPBEnumArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addRawValuesFromArray:otherArray]; + } else { + // The array type doesn't matter, that all implment + // -addValuesFromArray:. + GPBInt32Array *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addValuesFromArray:otherArray]; + } + } + } else { // fieldType = GPBFieldTypeMap + // In the case of a map, they need to be merged, and there is no + // _hasIvar to worry about setting. + id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (otherDict) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = field->description_->dataType; + if (GPBDataTypeIsObject(keyDataType) && + GPBDataTypeIsObject(valueDataType)) { + NSMutableDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } else if (valueDataType == GPBDataTypeEnum) { + // The exact type doesn't matter, just need to know it is a + // GPB*EnumDictionary. + GPBInt32EnumDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addRawEntriesFromDictionary:otherDict]; + } else { + // The exact type doesn't matter, they all implement + // -addEntriesFromDictionary:. + GPBInt32Int32Dictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } + } + } // if (fieldType)..else if...else + } // for(fields) + + // Unknown fields. + if (!unknownFields_) { + [self setUnknownFields:other.unknownFields]; + } else { + [unknownFields_ mergeUnknownFields:other.unknownFields]; + } + + // Extensions + + if (other->extensionMap_.count == 0) { + return; + } + + if (extensionMap_ == nil) { + extensionMap_ = + CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self)); + } else { + for (GPBExtensionDescriptor *extension in other->extensionMap_) { + id otherValue = [other->extensionMap_ objectForKey:extension]; + id value = [extensionMap_ objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); + + if (extension.repeated) { + NSMutableArray *list = value; + if (list == nil) { + list = [[NSMutableArray alloc] init]; + [extensionMap_ setObject:list forKey:extension]; + [list release]; + } + if (isMessageExtension) { + for (GPBMessage *otherListValue in otherValue) { + GPBMessage *copiedValue = [otherListValue copy]; + [list addObject:copiedValue]; + [copiedValue release]; + } + } else { + [list addObjectsFromArray:otherValue]; + } + } else { + if (isMessageExtension) { + if (value) { + [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; + } else { + GPBMessage *copiedValue = [otherValue copy]; + [extensionMap_ setObject:copiedValue forKey:extension]; + [copiedValue release]; + } + } else { + [extensionMap_ setObject:otherValue forKey:extension]; + } + } + + if (isMessageExtension && !extension.isRepeated) { + GPBMessage *autocreatedValue = + [[autocreatedExtensionMap_ objectForKey:extension] retain]; + // Must remove from the map before calling GPBClearMessageAutocreator() + // so that GPBClearMessageAutocreator() knows its safe to clear. + [autocreatedExtensionMap_ removeObjectForKey:extension]; + GPBClearMessageAutocreator(autocreatedValue); + [autocreatedValue release]; + } + } + } +} + +#pragma mark - isEqual: & hash Support + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (![other isKindOfClass:[GPBMessage class]]) { + return NO; + } + GPBMessage *otherMsg = other; + GPBDescriptor *descriptor = [[self class] descriptor]; + if ([[otherMsg class] descriptor] != descriptor) { + return NO; + } + uint8_t *selfStorage = (uint8_t *)messageStorage_; + uint8_t *otherStorage = (uint8_t *)otherMsg->messageStorage_; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + // In the case of a list or map, there is no _hasIvar to worry about. + // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but + // the type doesn't really matter as the objects all support -count and + // -isEqual:. + NSArray *resultMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + NSArray *otherMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + // nil and empty are equal + if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { + if (![resultMapOrArray isEqual:otherMapOrArray]) { + return NO; + } + } + } else { // Single field + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNum = GPBFieldNumber(field); + BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); + BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); + if (selfHas != otherHas) { + return NO; // Differing has values, not equal. + } + if (!selfHas) { + // Same has values, was no, nothing else to check for this field. + continue; + } + // Now compare the values. + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + // Bools are stored in has_bits to avoid needing explicit space in + // the storage structure. + // (the field number passed to the HasIvar helper doesn't really + // matter since the offset is never negative) + BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); + BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0); + if (selfValue != otherValue) { + return NO; + } + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, signed/unsigned doesn't matter for equality. + uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; + uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, signed/unsigned doesn't matter for equality. + uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; + uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + // Type doesn't matter here, they all implement -isEqual:. + id *selfValPtr = (id *)&selfStorage[fieldOffset]; + id *otherValPtr = (id *)&otherStorage[fieldOffset]; + if (![*selfValPtr isEqual:*otherValPtr]) { + return NO; + } + break; + } + } // switch() + } // if(mapOrArray)...else + } // for(fields) + + // nil and empty are equal + if (extensionMap_.count != 0 || otherMsg->extensionMap_.count != 0) { + if (![extensionMap_ isEqual:otherMsg->extensionMap_]) { + return NO; + } + } + + // nil and empty are equal + GPBUnknownFieldSet *otherUnknowns = otherMsg->unknownFields_; + if ([unknownFields_ countOfFields] != 0 || + [otherUnknowns countOfFields] != 0) { + if (![unknownFields_ isEqual:otherUnknowns]) { + return NO; + } + } + + return YES; +} + +// It is very difficult to implement a generic hash for ProtoBuf messages that +// will perform well. If you need hashing on your ProtoBufs (eg you are using +// them as dictionary keys) you will probably want to implement a ProtoBuf +// message specific hash as a category on your protobuf class. Do not make it a +// category on GPBMessage as you will conflict with this hash, and will possibly +// override hash for all generated protobufs. A good implementation of hash will +// be really fast, so we would recommend only hashing protobufs that have an +// identifier field of some kind that you can easily hash. If you implement +// hash, we would strongly recommend overriding isEqual: in your category as +// well, as the default implementation of isEqual: is extremely slow, and may +// drastically affect performance in large sets. +- (NSUInteger)hash { + GPBDescriptor *descriptor = [[self class] descriptor]; + const NSUInteger prime = 19; + uint8_t *storage = (uint8_t *)messageStorage_; + + // Start with the descriptor and then mix it with some instance info. + // Hopefully that will give a spread based on classes and what fields are set. + NSUInteger result = (NSUInteger)descriptor; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + // Exact type doesn't matter, just check if there are any elements. + NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + NSUInteger count = mapOrArray.count; + if (count) { + // NSArray/NSDictionary use count, use the field number and the count. + result = prime * result + GPBFieldNumber(field); + result = prime * result + count; + } + } else if (GPBGetHasIvarField(self, field)) { + // Just using the field number seemed simple/fast, but then a small + // message class where all the same fields are always set (to different + // things would end up all with the same hash, so pull in some data). + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + // Bools are stored in has_bits to avoid needing explicit space in + // the storage structure. + // (the field number passed to the HasIvar helper doesn't really + // matter since the offset is never negative) + BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); + result = prime * result + value; + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, just mix it in. + uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; + result = prime * result + *valPtr; + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, just mix what fits into an NSUInteger in. + uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; + result = prime * result + (NSUInteger)(*valPtr); + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: { + // Type doesn't matter here, they both implement -hash:. + id *valPtr = (id *)&storage[fieldOffset]; + result = prime * result + [*valPtr hash]; + break; + } + + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; + // Could call -hash on the sub message, but that could recurse pretty + // deep; follow the lead of NSArray/NSDictionary and don't really + // recurse for hash, instead use the field number and the descriptor + // of the sub message. Yes, this could suck for a bunch of messages + // where they all only differ in the sub messages, but if you are + // using a message with sub messages for something that needs -hash, + // odds are you are also copying them as keys, and that deep copy + // will also suck. + result = prime * result + GPBFieldNumber(field); + result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; + break; + } + } // switch() + } + } + + // Unknowns and extensions are not included. + + return result; +} + +#pragma mark - Description Support + +- (NSString *)description { + NSString *textFormat = GPBTextFormatForMessage(self, @" "); + NSString *description = [NSString + stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat]; + return description; +} + +#if defined(DEBUG) && DEBUG + +// Xcode 5.1 added support for custom quick look info. +// https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1 +- (id)debugQuickLookObject { + return GPBTextFormatForMessage(self, nil); +} + +#endif // DEBUG + +#pragma mark - SerializedSize + +- (size_t)serializedSize { + GPBDescriptor *descriptor = [[self class] descriptor]; + size_t result = 0; + + // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() + // avoids doing the has check again. + + // Fields. + for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); + + // Single Fields + if (fieldType == GPBFieldTypeSingle) { + BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); + if (!selfHas) { + continue; // Nothing to do. + } + + uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); + + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) + CASE_SINGLE_OBJECT(Message) + CASE_SINGLE_OBJECT(Group) + CASE_SINGLE_POD(Enum, int32_t, Int32) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + } + + // Repeated Fields + } else if (fieldType == GPBFieldTypeRepeated) { + id genericArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + NSUInteger count = [genericArray count]; + if (count == 0) { + continue; // Nothing to add. + } + __block size_t dataSize = 0; + + switch (fieldDataType) { +#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \ + CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) +#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ + case GPBDataType##NAME: { \ + GPB##ARRAY_TYPE##Array *array = genericArray; \ + [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \ + _Pragma("unused(idx, stop)"); \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + }]; \ + break; \ + } +#define CASE_REPEATED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + for (id value in genericArray) { \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + } \ + break; \ + } + CASE_REPEATED_POD(Bool, BOOL, Bool) + CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_POD(Float, float, Float) + CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_POD(Double, double, Double) + CASE_REPEATED_POD(Int32, int32_t, Int32) + CASE_REPEATED_POD(Int64, int64_t, Int64) + CASE_REPEATED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_OBJECT(Bytes) + CASE_REPEATED_OBJECT(String) + CASE_REPEATED_OBJECT(Message) + CASE_REPEATED_OBJECT(Group) + CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) +#undef CASE_REPEATED_POD +#undef CASE_REPEATED_POD_EXTRA +#undef CASE_REPEATED_OBJECT + } // switch + result += dataSize; + size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); + if (fieldDataType == GPBDataTypeGroup) { + // Groups have both a start and an end tag. + tagSize *= 2; + } + if (fieldDescriptor.isPackable) { + result += tagSize; + result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); + } else { + result += count * tagSize; + } + + // Map<> Fields + } else { // fieldType == GPBFieldTypeMap + if (GPBDataTypeIsObject(fieldDataType) && + (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { + // If key type was string, then the map is an NSDictionary. + NSDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + if (map) { + result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor); + } + } else { + // Type will be GPB*GroupDictionary, exact type doesn't matter. + GPBInt32Int32Dictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + result += [map computeSerializedSizeAsField:fieldDescriptor]; + } + } + } // for(fields) + + // Add any unknown fields. + if (descriptor.wireFormat) { + result += [unknownFields_ serializedSizeAsMessageSet]; + } else { + result += [unknownFields_ serializedSize]; + } + + // Add any extensions. + for (GPBExtensionDescriptor *extension in extensionMap_) { + id value = [extensionMap_ objectForKey:extension]; + result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); + } + + return result; +} + +#pragma mark - Resolve Methods Support + +typedef struct ResolveIvarAccessorMethodResult { + IMP impToAdd; + SEL encodingSelector; +} ResolveIvarAccessorMethodResult; + +// |field| can be __unsafe_unretained because they are created at startup +// and are essentially global. No need to pay for retain/release when +// they are captured in blocks. +static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_GET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetMessage##TRUE_NAME##Field(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } +#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetObjectIvarWithField(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } + CASE_GET(Bool, BOOL, Bool) + CASE_GET(Fixed32, uint32_t, UInt32) + CASE_GET(SFixed32, int32_t, Int32) + CASE_GET(Float, float, Float) + CASE_GET(Fixed64, uint64_t, UInt64) + CASE_GET(SFixed64, int64_t, Int64) + CASE_GET(Double, double, Double) + CASE_GET(Int32, int32_t, Int32) + CASE_GET(Int64, int64_t, Int64) + CASE_GET(SInt32, int32_t, Int32) + CASE_GET(SInt64, int64_t, Int64) + CASE_GET(UInt32, uint32_t, UInt32) + CASE_GET(UInt64, uint64_t, UInt64) + CASE_GET_OBJECT(Bytes, id, Object) + CASE_GET_OBJECT(String, id, Object) + CASE_GET_OBJECT(Message, id, Object) + CASE_GET_OBJECT(Group, id, Object) + CASE_GET(Enum, int32_t, Enum) +#undef CASE_GET + } +} + +// See comment about __unsafe_unretained on ResolveIvarGet. +static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, + GPBFileSyntax syntax, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ + return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } +#define CASE_SET_COPY(NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \ + return GPBSetRetainedObjectIvarWithFieldInternal(obj, field, [value copy], syntax); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } + CASE_SET(Bool, BOOL, Bool) + CASE_SET(Fixed32, uint32_t, UInt32) + CASE_SET(SFixed32, int32_t, Int32) + CASE_SET(Float, float, Float) + CASE_SET(Fixed64, uint64_t, UInt64) + CASE_SET(SFixed64, int64_t, Int64) + CASE_SET(Double, double, Double) + CASE_SET(Int32, int32_t, Int32) + CASE_SET(Int64, int64_t, Int64) + CASE_SET(SInt32, int32_t, Int32) + CASE_SET(SInt64, int64_t, Int64) + CASE_SET(UInt32, uint32_t, UInt32) + CASE_SET(UInt64, uint64_t, UInt64) + CASE_SET_COPY(Bytes) + CASE_SET_COPY(String) + CASE_SET(Message, id, Object) + CASE_SET(Group, id, Object) + CASE_SET(Enum, int32_t, Enum) +#undef CASE_SET + } +} + ++ (BOOL)resolveInstanceMethod:(SEL)sel { + const GPBDescriptor *descriptor = [self descriptor]; + if (!descriptor) { + return [super resolveInstanceMethod:sel]; + } + + // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given + // message should not have has support (done in GPBDescriptor.m), so there is + // no need for checks here to see if has*/setHas* are allowed. + ResolveIvarAccessorMethodResult result = {NULL, NULL}; + + // See comment about __unsafe_unretained on ResolveIvarGet. + for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) { + BOOL isMapOrArray = GPBFieldIsMapOrArray(field); + if (!isMapOrArray) { + // Single fields. + if (sel == field->getSel_) { + ResolveIvarGet(field, &result); + break; + } else if (sel == field->setSel_) { + ResolveIvarSet(field, descriptor.file.syntax, &result); + break; + } else if (sel == field->hasOrCountSel_) { + int32_t index = GPBFieldHasIndex(field); + uint32_t fieldNum = GPBFieldNumber(field); + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GPBGetHasIvar(obj, index, fieldNum); + }); + result.encodingSelector = @selector(getBool); + break; + } else if (sel == field->setHasSel_) { + result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { + if (value) { + [NSException raise:NSInvalidArgumentException + format:@"%@: %@ can only be set to NO (to clear field).", + [obj class], + NSStringFromSelector(field->setHasSel_)]; + } + GPBClearMessageField(obj, field); + }); + result.encodingSelector = @selector(setBool:); + break; + } else { + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof && (sel == oneof->caseSel_)) { + int32_t index = GPBFieldHasIndex(field); + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GPBGetHasOneof(obj, index); + }); + result.encodingSelector = @selector(getEnum); + break; + } + } + } else { + // map<>/repeated fields. + if (sel == field->getSel_) { + if (field.fieldType == GPBFieldTypeRepeated) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GetArrayIvarWithField(obj, field); + }); + } else { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GetMapIvarWithField(obj, field); + }); + } + result.encodingSelector = @selector(getArray); + break; + } else if (sel == field->setSel_) { + // Local for syntax so the block can directly capture it and not the + // full lookup. + const GPBFileSyntax syntax = descriptor.file.syntax; + result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { + GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); + }); + result.encodingSelector = @selector(setArray:); + break; + } else if (sel == field->hasOrCountSel_) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + // Type doesn't matter, all *Array and *Dictionary types support + // -count. + NSArray *arrayOrMap = + GPBGetObjectIvarWithFieldNoAutocreate(obj, field); + return [arrayOrMap count]; + }); + result.encodingSelector = @selector(getArrayCount); + break; + } + } + } + if (result.impToAdd) { + const char *encoding = + GPBMessageEncodingForSelector(result.encodingSelector, YES); + Class msgClass = descriptor.messageClass; + BOOL methodAdded = class_addMethod(msgClass, sel, result.impToAdd, encoding); + // class_addMethod() is documented as also failing if the method was already + // added; so we check if the method is already there and return success so + // the method dispatch will still happen. Why would it already be added? + // Two threads could cause the same method to be bound at the same time, + // but only one will actually bind it; the other still needs to return true + // so things will dispatch. + if (!methodAdded) { + methodAdded = GPBClassHasSel(msgClass, sel); + } + return methodAdded; + } + return [super resolveInstanceMethod:sel]; +} + ++ (BOOL)resolveClassMethod:(SEL)sel { + // Extensions scoped to a Message and looked up via class methods. + if (GPBResolveExtensionClassMethod([self descriptor].messageClass, sel)) { + return YES; + } + return [super resolveClassMethod:sel]; +} + +#pragma mark - NSCoding Support + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [self init]; + if (self) { + NSData *data = + [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; + if (data.length) { + [self mergeFromData:data extensionRegistry:nil]; + } + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { +#if defined(DEBUG) && DEBUG + if (extensionMap_.count) { + // Hint to go along with the docs on GPBMessage about this. + // + // Note: This is incomplete, in that it only checked the "root" message, + // if a sub message in a field has extensions, the issue still exists. A + // recursive check could be done here (like the work in + // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to + // be expensive and could slow down serialization in DEBUG enought to cause + // developers other problems. + NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it" + @" has %ld extensions; when read back in, those fields will be" + @" in the unknownFields property instead.", + [self class], (long)extensionMap_.count); + } +#endif + NSData *data = [self data]; + if (data.length) { + [aCoder encodeObject:data forKey:kGPBDataCoderKey]; + } +} + +#pragma mark - KVC Support + ++ (BOOL)accessInstanceVariablesDirectly { + // Make sure KVC doesn't use instance variables. + return NO; +} + +@end + +#pragma mark - Messages from GPBUtilities.h but defined here for access to helpers. + +// Only exists for public api, no core code should use this. +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } +#endif + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + return GetOrCreateArrayIvarWithField(self, field, syntax); +} + +// Only exists for public api, no core code should use this. +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } +#endif + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + return GetOrCreateMapIvarWithField(self, field, syntax); +} + +id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + return *typePtr; + } + // Not set... + + // Non messages (string/data), get their default. + if (!GPBFieldDataTypeIsMessage(field)) { + return field.defaultValue.valueMessage; + } + + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); + GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!result) { + // For non repeated messages, create the object, set it and return it. + // This object will not initially be visible via GPBGetHasIvar, so + // we save its creator so it can become visible if it's mutated later. + result = GPBCreateMessageWithAutocreator(field.msgClass, self, field); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result); + } + dispatch_semaphore_signal(self->readOnlySemaphore_); + return result; +} + +#pragma clang diagnostic pop diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage_PackagePrivate.h new file mode 100644 index 0000000..ca10983 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBMessage_PackagePrivate.h @@ -0,0 +1,124 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is private to the ProtobolBuffers library and must NOT be +// included by any sources outside this library. The contents of this file are +// subject to change at any time without notice. + +#import "GPBMessage.h" + +// TODO: Remove this import. Older generated code use the OSAtomic* apis, +// so anyone that hasn't regenerated says building by having this. After +// enough time has passed, this likely can be removed as folks should have +// regenerated. +#import + +#import "GPBBootstrap.h" + +typedef struct GPBMessage_Storage { + uint32_t _has_storage_[0]; +} GPBMessage_Storage; + +typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; + +@interface GPBMessage () { + @package + // NOTE: Because of the +allocWithZone code using NSAllocateObject(), + // this structure should ideally always be kept pointer aligned where the + // real storage starts is also pointer aligned. The compiler/runtime already + // do this, but it may not be documented. + + // A pointer to the actual fields of the subclasses. The actual structure + // pointed to by this pointer will depend on the subclass. + // All of the actual structures will start the same as + // GPBMessage_Storage with _has_storage__ as the first field. + // Kept public because static functions need to access it. + GPBMessage_StoragePtr messageStorage_; +} + +// Gets an extension value without autocreating the result if not found. (i.e. +// returns nil if the extension is not set) +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension; + +// Parses a message of this type from the input and merges it with this +// message. +// +// Warning: This does not verify that all required fields are present in +// the input message. +// Note: The caller should call +// -[CodedInputStream checkLastTagWas:] after calling this to +// verify that the last tag seen was the appropriate end-group tag, +// or zero for EOF. +// NOTE: This will throw if there is an error while parsing. +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + +// Parses the next delimited message of this type from the input and merges it +// with this message. +- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (GPBExtensionRegistry *)extensionRegistry; + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data; + +@end + +CF_EXTERN_C_BEGIN + + +// Call this before using the readOnlySemaphore_. This ensures it is created only once. +void GPBPrepareReadOnlySemaphore(GPBMessage *self); + +// Returns a new instance that was automatically created by |autocreator| for +// its field |field|. +GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, + GPBMessage *autocreator, + GPBFieldDescriptor *field) + __attribute__((ns_returns_retained)); + +// Returns whether |message| autocreated this message. This is NO if the message +// was not autocreated by |message| or if it has been mutated since +// autocreation. +BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent); + +// Call this when you mutate a message. It will cause the message to become +// visible to its autocreator. +void GPBBecomeVisibleToAutocreator(GPBMessage *self); + +// Call this when an array/dictionary is mutated so the parent message that +// autocreated it can react. +void GPBAutocreatedArrayModified(GPBMessage *self, id array); +void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary); + +// Clear the autocreator, if any. Asserts if the autocreator still has an +// autocreated reference to this message. +void GPBClearMessageAutocreator(GPBMessage *self); + +CF_EXTERN_C_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBProtocolBuffers.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBProtocolBuffers.h new file mode 100644 index 0000000..68d8854 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBProtocolBuffers.h @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBBootstrap.h" + +#import "GPBArray.h" +#import "GPBCodedInputStream.h" +#import "GPBCodedOutputStream.h" +#import "GPBDescriptor.h" +#import "GPBDictionary.h" +#import "GPBExtensionRegistry.h" +#import "GPBMessage.h" +#import "GPBRootObject.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFieldSet.h" +#import "GPBUtilities.h" +#import "GPBWellKnownTypes.h" +#import "GPBWireFormat.h" + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +// Well-known proto types +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import +#else + #import "google/protobuf/Any.pbobjc.h" + #import "google/protobuf/Api.pbobjc.h" + #import "google/protobuf/Duration.pbobjc.h" + #import "google/protobuf/Empty.pbobjc.h" + #import "google/protobuf/FieldMask.pbobjc.h" + #import "google/protobuf/SourceContext.pbobjc.h" + #import "google/protobuf/Struct.pbobjc.h" + #import "google/protobuf/Timestamp.pbobjc.h" + #import "google/protobuf/Type.pbobjc.h" + #import "google/protobuf/Wrappers.pbobjc.h" +#endif diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBProtocolBuffers_RuntimeSupport.h new file mode 100644 index 0000000..04dde62 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBProtocolBuffers_RuntimeSupport.h @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is meant to only be used by the generated source, it should not +// be included in code using protocol buffers. + +#import "GPBBootstrap.h" + +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBExtensionInternals.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBRootObject_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject.h new file mode 100644 index 0000000..d2e2aeb --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject.h @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBExtensionRegistry; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Every generated proto file defines a local "Root" class that exposes a + * GPBExtensionRegistry for all the extensions defined by that file and + * the files it depends on. + **/ +@interface GPBRootObject : NSObject + +/** + * @return An extension registry for the given file and all the files it depends + * on. + **/ ++ (GPBExtensionRegistry *)extensionRegistry; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject.m new file mode 100644 index 0000000..bad2f9a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject.m @@ -0,0 +1,245 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBRootObject_PackagePrivate.h" + +#import + +#import + +#import "GPBDescriptor.h" +#import "GPBExtensionRegistry.h" +#import "GPBUtilities_PackagePrivate.h" + +@interface GPBExtensionDescriptor (GPBRootObject) +// Get singletonName as a c string. +- (const char *)singletonNameC; +@end + +// We need some object to conform to the MessageSignatureProtocol to make sure +// the selectors in it are recorded in our Objective C runtime information. +// GPBMessage is arguably the more "obvious" choice, but given that all messages +// inherit from GPBMessage, conflicts seem likely, so we are using GPBRootObject +// instead. +@interface GPBRootObject () +@end + +@implementation GPBRootObject + +// Taken from http://www.burtleburtle.net/bob/hash/doobs.html +// Public Domain +static uint32_t jenkins_one_at_a_time_hash(const char *key) { + uint32_t hash = 0; + for (uint32_t i = 0; key[i] != '\0'; ++i) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; +} + +// Key methods for our custom CFDictionary. +// Note that the dictionary lasts for the lifetime of our app, so no need +// to worry about deallocation. All of the items are added to it at +// startup, and so the keys don't need to be retained/released. +// Keys are NULL terminated char *. +static const void *GPBRootExtensionKeyRetain(CFAllocatorRef allocator, + const void *value) { +#pragma unused(allocator) + return value; +} + +static void GPBRootExtensionKeyRelease(CFAllocatorRef allocator, + const void *value) { +#pragma unused(allocator) +#pragma unused(value) +} + +static CFStringRef GPBRootExtensionCopyKeyDescription(const void *value) { + const char *key = (const char *)value; + return CFStringCreateWithCString(kCFAllocatorDefault, key, + kCFStringEncodingUTF8); +} + +static Boolean GPBRootExtensionKeyEqual(const void *value1, + const void *value2) { + const char *key1 = (const char *)value1; + const char *key2 = (const char *)value2; + return strcmp(key1, key2) == 0; +} + +static CFHashCode GPBRootExtensionKeyHash(const void *value) { + const char *key = (const char *)value; + return jenkins_one_at_a_time_hash(key); +} + +// NOTE: OSSpinLock may seem like a good fit here but Apple engineers have +// pointed out that they are vulnerable to live locking on iOS in cases of +// priority inversion: +// http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ +// https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html +static dispatch_semaphore_t gExtensionSingletonDictionarySemaphore; +static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; +static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL; + ++ (void)initialize { + // Ensure the global is started up. + if (!gExtensionSingletonDictionary) { + gExtensionSingletonDictionarySemaphore = dispatch_semaphore_create(1); + CFDictionaryKeyCallBacks keyCallBacks = { + // See description above for reason for using custom dictionary. + 0, + GPBRootExtensionKeyRetain, + GPBRootExtensionKeyRelease, + GPBRootExtensionCopyKeyDescription, + GPBRootExtensionKeyEqual, + GPBRootExtensionKeyHash, + }; + gExtensionSingletonDictionary = + CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, + &kCFTypeDictionaryValueCallBacks); + gDefaultExtensionRegistry = [[GPBExtensionRegistry alloc] init]; + } + + if ([self superclass] == [GPBRootObject class]) { + // This is here to start up all the per file "Root" subclasses. + // This must be done in initialize to enforce thread safety of start up of + // the protocol buffer library. + [self extensionRegistry]; + } +} + ++ (GPBExtensionRegistry *)extensionRegistry { + // Is overridden in all the subclasses that provide extensions to provide the + // per class one. + return gDefaultExtensionRegistry; +} + ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field { + const char *key = [field singletonNameC]; + dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore, + DISPATCH_TIME_FOREVER); + CFDictionarySetValue(gExtensionSingletonDictionary, key, field); + dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore); +} + +static id ExtensionForName(id self, SEL _cmd) { + // Really fast way of doing "classname_selName". + // This came up as a hotspot (creation of NSString *) when accessing a + // lot of extensions. + const char *selName = sel_getName(_cmd); + if (selName[0] == '_') { + return nil; // Apple internal selector. + } + size_t selNameLen = 0; + while (1) { + char c = selName[selNameLen]; + if (c == '\0') { // String end. + break; + } + if (c == ':') { + return nil; // Selector took an arg, not one of the runtime methods. + } + ++selNameLen; + } + + const char *className = class_getName(self); + size_t classNameLen = strlen(className); + char key[classNameLen + selNameLen + 2]; + memcpy(key, className, classNameLen); + key[classNameLen] = '_'; + memcpy(&key[classNameLen + 1], selName, selNameLen); + key[classNameLen + 1 + selNameLen] = '\0'; + + // NOTE: Even though this method is called from another C function, + // gExtensionSingletonDictionarySemaphore and gExtensionSingletonDictionary + // will always be initialized. This is because this call flow is just to + // lookup the Extension, meaning the code is calling an Extension class + // message on a Message or Root class. This guarantees that the class was + // initialized and Message classes ensure their Root was also initialized. + NSAssert(gExtensionSingletonDictionary, @"Startup order broken!"); + + dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore, + DISPATCH_TIME_FOREVER); + id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key); + // We can't remove the key from the dictionary here (as an optimization), + // two threads could have gone into +resolveClassMethod: for the same method, + // and ended up here; there's no way to ensure both return YES without letting + // both try to wire in the method. + dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore); + return extension; +} + +BOOL GPBResolveExtensionClassMethod(Class self, SEL sel) { + // Another option would be to register the extensions with the class at + // globallyRegisterExtension: + // Timing the two solutions, this solution turned out to be much faster + // and reduced startup time, and runtime memory. + // The advantage to globallyRegisterExtension is that it would reduce the + // size of the protos somewhat because the singletonNameC wouldn't need + // to include the class name. For a class with a lot of extensions it + // can add up. You could also significantly reduce the code complexity of this + // file. + id extension = ExtensionForName(self, sel); + if (extension != nil) { + const char *encoding = + GPBMessageEncodingForSelector(@selector(getClassValue), NO); + Class metaClass = objc_getMetaClass(class_getName(self)); + IMP imp = imp_implementationWithBlock(^(id obj) { +#pragma unused(obj) + return extension; + }); + BOOL methodAdded = class_addMethod(metaClass, sel, imp, encoding); + // class_addMethod() is documented as also failing if the method was already + // added; so we check if the method is already there and return success so + // the method dispatch will still happen. Why would it already be added? + // Two threads could cause the same method to be bound at the same time, + // but only one will actually bind it; the other still needs to return true + // so things will dispatch. + if (!methodAdded) { + methodAdded = GPBClassHasSel(metaClass, sel); + } + return methodAdded; + } + return NO; +} + + ++ (BOOL)resolveClassMethod:(SEL)sel { + if (GPBResolveExtensionClassMethod(self, sel)) { + return YES; + } + return [super resolveClassMethod:sel]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject_PackagePrivate.h new file mode 100644 index 0000000..3c8f09c --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRootObject_PackagePrivate.h @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRootObject.h" + +@class GPBExtensionDescriptor; + +@interface GPBRootObject () + +// Globally register. ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field; + +@end + +// Returns YES if the selector was resolved and added to the class, +// NO otherwise. +BOOL GPBResolveExtensionClassMethod(Class self, SEL sel); diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRuntimeTypes.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRuntimeTypes.h new file mode 100644 index 0000000..4d55206 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBRuntimeTypes.h @@ -0,0 +1,144 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBBootstrap.h" + +@class GPBEnumDescriptor; +@class GPBMessage; +@class GPBInt32Array; + +/** + * Verifies that a given value can be represented by an enum type. + * */ +typedef BOOL (*GPBEnumValidationFunc)(int32_t); + +/** + * Fetches an EnumDescriptor. + * */ +typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void); + +/** + * Magic value used at runtime to indicate an enum value that wasn't know at + * compile time. + * */ +enum { + kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF, +}; + +/** + * A union for storing all possible Protobuf values. Note that owner is + * responsible for memory management of object types. + * */ +typedef union { + BOOL valueBool; + int32_t valueInt32; + int64_t valueInt64; + uint32_t valueUInt32; + uint64_t valueUInt64; + float valueFloat; + double valueDouble; + GPB_UNSAFE_UNRETAINED NSData *valueData; + GPB_UNSAFE_UNRETAINED NSString *valueString; + GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage; + int32_t valueEnum; +} GPBGenericValue; + +/** + * Enum listing the possible data types that a field can contain. + * + * @note Do not change the order of this enum (or add things to it) without + * thinking about it very carefully. There are several things that depend + * on the order. + * */ +typedef NS_ENUM(uint8_t, GPBDataType) { + /** Field contains boolean value(s). */ + GPBDataTypeBool = 0, + /** Field contains unsigned 4 byte value(s). */ + GPBDataTypeFixed32, + /** Field contains signed 4 byte value(s). */ + GPBDataTypeSFixed32, + /** Field contains float value(s). */ + GPBDataTypeFloat, + /** Field contains unsigned 8 byte value(s). */ + GPBDataTypeFixed64, + /** Field contains signed 8 byte value(s). */ + GPBDataTypeSFixed64, + /** Field contains double value(s). */ + GPBDataTypeDouble, + /** + * Field contains variable length value(s). Inefficient for encoding negative + * numbers – if your field is likely to have negative values, use + * GPBDataTypeSInt32 instead. + **/ + GPBDataTypeInt32, + /** + * Field contains variable length value(s). Inefficient for encoding negative + * numbers – if your field is likely to have negative values, use + * GPBDataTypeSInt64 instead. + **/ + GPBDataTypeInt64, + /** Field contains signed variable length integer value(s). */ + GPBDataTypeSInt32, + /** Field contains signed variable length integer value(s). */ + GPBDataTypeSInt64, + /** Field contains unsigned variable length integer value(s). */ + GPBDataTypeUInt32, + /** Field contains unsigned variable length integer value(s). */ + GPBDataTypeUInt64, + /** Field contains an arbitrary sequence of bytes. */ + GPBDataTypeBytes, + /** Field contains UTF-8 encoded or 7-bit ASCII text. */ + GPBDataTypeString, + /** Field contains message type(s). */ + GPBDataTypeMessage, + /** Field contains message type(s). */ + GPBDataTypeGroup, + /** Field contains enum value(s). */ + GPBDataTypeEnum, +}; + +enum { + /** + * A count of the number of types in GPBDataType. Separated out from the + * GPBDataType enum to avoid warnings regarding not handling GPBDataType_Count + * in switch statements. + **/ + GPBDataType_Count = GPBDataTypeEnum + 1 +}; + +/** An extension range. */ +typedef struct GPBExtensionRange { + /** Inclusive. */ + uint32_t start; + /** Exclusive. */ + uint32_t end; +} GPBExtensionRange; diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField.h new file mode 100644 index 0000000..5b96023 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField.h @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBCodedOutputStream; +@class GPBUInt32Array; +@class GPBUInt64Array; +@class GPBUnknownFieldSet; + +NS_ASSUME_NONNULL_BEGIN +/** + * Store an unknown field. These are used in conjunction with + * GPBUnknownFieldSet. + **/ +@interface GPBUnknownField : NSObject + +/** Initialize a field with the given number. */ +- (instancetype)initWithNumber:(int32_t)number; + +/** The field number the data is stored under. */ +@property(nonatomic, readonly, assign) int32_t number; + +/** An array of varint values for this field. */ +@property(nonatomic, readonly, strong) GPBUInt64Array *varintList; + +/** An array of fixed32 values for this field. */ +@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List; + +/** An array of fixed64 values for this field. */ +@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List; + +/** An array of data values for this field. */ +@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList; + +/** An array of groups of values for this field. */ +@property(nonatomic, readonly, strong) NSArray *groupList; + +/** + * Add a value to the varintList. + * + * @param value The value to add. + **/ +- (void)addVarint:(uint64_t)value; +/** + * Add a value to the fixed32List. + * + * @param value The value to add. + **/ +- (void)addFixed32:(uint32_t)value; +/** + * Add a value to the fixed64List. + * + * @param value The value to add. + **/ +- (void)addFixed64:(uint64_t)value; +/** + * Add a value to the lengthDelimitedList. + * + * @param value The value to add. + **/ +- (void)addLengthDelimited:(NSData *)value; +/** + * Add a value to the groupList. + * + * @param value The value to add. + **/ +- (void)addGroup:(GPBUnknownFieldSet *)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField.m new file mode 100644 index 0000000..7fa8cad --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField.m @@ -0,0 +1,337 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBUnknownField_PackagePrivate.h" + +#import "GPBArray.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBUnknownFieldSet.h" + +@implementation GPBUnknownField { + @protected + int32_t number_; + GPBUInt64Array *mutableVarintList_; + GPBUInt32Array *mutableFixed32List_; + GPBUInt64Array *mutableFixed64List_; + NSMutableArray *mutableLengthDelimitedList_; + NSMutableArray *mutableGroupList_; +} + +@synthesize number = number_; +@synthesize varintList = mutableVarintList_; +@synthesize fixed32List = mutableFixed32List_; +@synthesize fixed64List = mutableFixed64List_; +@synthesize lengthDelimitedList = mutableLengthDelimitedList_; +@synthesize groupList = mutableGroupList_; + +- (instancetype)initWithNumber:(int32_t)number { + if ((self = [super init])) { + number_ = number; + } + return self; +} + +- (void)dealloc { + [mutableVarintList_ release]; + [mutableFixed32List_ release]; + [mutableFixed64List_ release]; + [mutableLengthDelimitedList_ release]; + [mutableGroupList_ release]; + + [super dealloc]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (id)copyWithZone:(NSZone *)zone { + GPBUnknownField *result = + [[GPBUnknownField allocWithZone:zone] initWithNumber:number_]; + result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; + result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; + result->mutableLengthDelimitedList_ = + [mutableLengthDelimitedList_ mutableCopyWithZone:zone]; + result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone]; + if (mutableGroupList_.count) { + result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone] + initWithCapacity:mutableGroupList_.count]; + for (GPBUnknownFieldSet *group in mutableGroupList_) { + GPBUnknownFieldSet *copied = [group copyWithZone:zone]; + [result->mutableGroupList_ addObject:copied]; + [copied release]; + } + } + return result; +} + +- (BOOL)isEqual:(id)object { + if (self == object) return YES; + if (![object isKindOfClass:[GPBUnknownField class]]) return NO; + GPBUnknownField *field = (GPBUnknownField *)object; + if (number_ != field->number_) return NO; + BOOL equalVarint = + (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || + [mutableVarintList_ isEqual:field->mutableVarintList_]; + if (!equalVarint) return NO; + BOOL equalFixed32 = (mutableFixed32List_.count == 0 && + field->mutableFixed32List_.count == 0) || + [mutableFixed32List_ isEqual:field->mutableFixed32List_]; + if (!equalFixed32) return NO; + BOOL equalFixed64 = (mutableFixed64List_.count == 0 && + field->mutableFixed64List_.count == 0) || + [mutableFixed64List_ isEqual:field->mutableFixed64List_]; + if (!equalFixed64) return NO; + BOOL equalLDList = + (mutableLengthDelimitedList_.count == 0 && + field->mutableLengthDelimitedList_.count == 0) || + [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_]; + if (!equalLDList) return NO; + BOOL equalGroupList = + (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) || + [mutableGroupList_ isEqual:field->mutableGroupList_]; + if (!equalGroupList) return NO; + return YES; +} + +- (NSUInteger)hash { + // Just mix the hashes of the possible sub arrays. + const int prime = 31; + NSUInteger result = prime + [mutableVarintList_ hash]; + result = prime * result + [mutableFixed32List_ hash]; + result = prime * result + [mutableFixed64List_ hash]; + result = prime * result + [mutableLengthDelimitedList_ hash]; + result = prime * result + [mutableGroupList_ hash]; + return result; +} + +- (void)writeToOutput:(GPBCodedOutputStream *)output { + NSUInteger count = mutableVarintList_.count; + if (count > 0) { + [output writeUInt64Array:number_ values:mutableVarintList_ tag:0]; + } + count = mutableFixed32List_.count; + if (count > 0) { + [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0]; + } + count = mutableFixed64List_.count; + if (count > 0) { + [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0]; + } + count = mutableLengthDelimitedList_.count; + if (count > 0) { + [output writeBytesArray:number_ values:mutableLengthDelimitedList_]; + } + count = mutableGroupList_.count; + if (count > 0) { + [output writeUnknownGroupArray:number_ values:mutableGroupList_]; + } +} + +- (size_t)serializedSize { + __block size_t result = 0; + int32_t number = number_; + [mutableVarintList_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeUInt64Size(number, value); + }]; + + [mutableFixed32List_ + enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeFixed32Size(number, value); + }]; + + [mutableFixed64List_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeFixed64Size(number, value); + }]; + + for (NSData *data in mutableLengthDelimitedList_) { + result += GPBComputeBytesSize(number, data); + } + + for (GPBUnknownFieldSet *set in mutableGroupList_) { + result += GPBComputeUnknownGroupSize(number, set); + } + + return result; +} + +- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output { + for (NSData *data in mutableLengthDelimitedList_) { + [output writeRawMessageSetExtension:number_ value:data]; + } +} + +- (size_t)serializedSizeAsMessageSetExtension { + size_t result = 0; + for (NSData *data in mutableLengthDelimitedList_) { + result += GPBComputeRawMessageSetExtensionSize(number_, data); + } + return result; +} + +- (NSString *)description { + NSMutableString *description = + [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n", + [self class], self, number_]; + [mutableVarintList_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%llu\n", value]; + }]; + + [mutableFixed32List_ + enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%u\n", value]; + }]; + + [mutableFixed64List_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%llu\n", value]; + }]; + + for (NSData *data in mutableLengthDelimitedList_) { + [description appendFormat:@"\t%@\n", data]; + } + + for (GPBUnknownFieldSet *set in mutableGroupList_) { + [description appendFormat:@"\t%@\n", set]; + } + [description appendString:@"}"]; + return description; +} + +- (void)mergeFromField:(GPBUnknownField *)other { + GPBUInt64Array *otherVarintList = other.varintList; + if (otherVarintList.count > 0) { + if (mutableVarintList_ == nil) { + mutableVarintList_ = [otherVarintList copy]; + } else { + [mutableVarintList_ addValuesFromArray:otherVarintList]; + } + } + + GPBUInt32Array *otherFixed32List = other.fixed32List; + if (otherFixed32List.count > 0) { + if (mutableFixed32List_ == nil) { + mutableFixed32List_ = [otherFixed32List copy]; + } else { + [mutableFixed32List_ addValuesFromArray:otherFixed32List]; + } + } + + GPBUInt64Array *otherFixed64List = other.fixed64List; + if (otherFixed64List.count > 0) { + if (mutableFixed64List_ == nil) { + mutableFixed64List_ = [otherFixed64List copy]; + } else { + [mutableFixed64List_ addValuesFromArray:otherFixed64List]; + } + } + + NSArray *otherLengthDelimitedList = other.lengthDelimitedList; + if (otherLengthDelimitedList.count > 0) { + if (mutableLengthDelimitedList_ == nil) { + mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy]; + } else { + [mutableLengthDelimitedList_ + addObjectsFromArray:otherLengthDelimitedList]; + } + } + + NSArray *otherGroupList = other.groupList; + if (otherGroupList.count > 0) { + if (mutableGroupList_ == nil) { + mutableGroupList_ = + [[NSMutableArray alloc] initWithCapacity:otherGroupList.count]; + } + // Make our own mutable copies. + for (GPBUnknownFieldSet *group in otherGroupList) { + GPBUnknownFieldSet *copied = [group copy]; + [mutableGroupList_ addObject:copied]; + [copied release]; + } + } +} + +- (void)addVarint:(uint64_t)value { + if (mutableVarintList_ == nil) { + mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1]; + } else { + [mutableVarintList_ addValue:value]; + } +} + +- (void)addFixed32:(uint32_t)value { + if (mutableFixed32List_ == nil) { + mutableFixed32List_ = + [[GPBUInt32Array alloc] initWithValues:&value count:1]; + } else { + [mutableFixed32List_ addValue:value]; + } +} + +- (void)addFixed64:(uint64_t)value { + if (mutableFixed64List_ == nil) { + mutableFixed64List_ = + [[GPBUInt64Array alloc] initWithValues:&value count:1]; + } else { + [mutableFixed64List_ addValue:value]; + } +} + +- (void)addLengthDelimited:(NSData *)value { + if (mutableLengthDelimitedList_ == nil) { + mutableLengthDelimitedList_ = + [[NSMutableArray alloc] initWithObjects:&value count:1]; + } else { + [mutableLengthDelimitedList_ addObject:value]; + } +} + +- (void)addGroup:(GPBUnknownFieldSet *)value { + if (mutableGroupList_ == nil) { + mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1]; + } else { + [mutableGroupList_ addObject:value]; + } +} + +#pragma clang diagnostic pop + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.h new file mode 100644 index 0000000..1b5f24f --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.h @@ -0,0 +1,82 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBUnknownField; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A collection of unknown fields. Fields parsed from the binary representation + * of a message that are unknown end up in an instance of this set. This only + * applies for files declared with the "proto2" syntax. Files declared with the + * "proto3" syntax discard the unknown values. + **/ +@interface GPBUnknownFieldSet : NSObject + +/** + * Tests to see if the given field number has a value. + * + * @param number The field number to check. + * + * @return YES if there is an unknown field for the given field number. + **/ +- (BOOL)hasField:(int32_t)number; + +/** + * Fetches the GPBUnknownField for the given field number. + * + * @param number The field number to look up. + * + * @return The GPBUnknownField or nil if none found. + **/ +- (nullable GPBUnknownField *)getField:(int32_t)number; + +/** + * @return The number of fields in this set. + **/ +- (NSUInteger)countOfFields; + +/** + * Adds the given field to the set. + * + * @param field The field to add to the set. + **/ +- (void)addField:(GPBUnknownField *)field; + +/** + * @return An array of the GPBUnknownFields sorted by the field numbers. + **/ +- (NSArray *)sortedFields; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.m new file mode 100644 index 0000000..a7335f0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.m @@ -0,0 +1,395 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBUnknownFieldSet_PackagePrivate.h" + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" +#import "GPBUnknownField_PackagePrivate.h" +#import "GPBUtilities.h" +#import "GPBWireFormat.h" + +#pragma mark Helpers + +static void checkNumber(int32_t number) { + if (number == 0) { + [NSException raise:NSInvalidArgumentException + format:@"Zero is not a valid field number."]; + } +} + +@implementation GPBUnknownFieldSet { + @package + CFMutableDictionaryRef fields_; +} + +static void CopyWorker(const void *key, const void *value, void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + GPBUnknownFieldSet *result = context; + + GPBUnknownField *copied = [field copy]; + [result addField:copied]; + [copied release]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (id)copyWithZone:(NSZone *)zone { + GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; + if (fields_) { + CFDictionaryApplyFunction(fields_, CopyWorker, result); + } + return result; +} + +- (void)dealloc { + if (fields_) { + CFRelease(fields_); + } + [super dealloc]; +} + +- (BOOL)isEqual:(id)object { + BOOL equal = NO; + if ([object isKindOfClass:[GPBUnknownFieldSet class]]) { + GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object; + if ((fields_ == NULL) && (set->fields_ == NULL)) { + equal = YES; + } else if ((fields_ != NULL) && (set->fields_ != NULL)) { + equal = CFEqual(fields_, set->fields_); + } + } + return equal; +} + +- (NSUInteger)hash { + // Return the hash of the fields dictionary (or just some value). + if (fields_) { + return CFHash(fields_); + } + return (NSUInteger)[GPBUnknownFieldSet class]; +} + +#pragma mark - Public Methods + +- (BOOL)hasField:(int32_t)number { + ssize_t key = number; + return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; +} + +- (GPBUnknownField *)getField:(int32_t)number { + ssize_t key = number; + GPBUnknownField *result = + fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; + return result; +} + +- (NSUInteger)countOfFields { + return fields_ ? CFDictionaryGetCount(fields_) : 0; +} + +- (NSArray *)sortedFields { + if (!fields_) return [NSArray array]; + size_t count = CFDictionaryGetCount(fields_); + ssize_t keys[count]; + GPBUnknownField *values[count]; + CFDictionaryGetKeysAndValues(fields_, (const void **)keys, + (const void **)values); + struct GPBFieldPair { + ssize_t key; + GPBUnknownField *value; + } pairs[count]; + for (size_t i = 0; i < count; ++i) { + pairs[i].key = keys[i]; + pairs[i].value = values[i]; + }; + qsort_b(pairs, count, sizeof(struct GPBFieldPair), + ^(const void *first, const void *second) { + const struct GPBFieldPair *a = first; + const struct GPBFieldPair *b = second; + return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); + }); + for (size_t i = 0; i < count; ++i) { + values[i] = pairs[i].value; + }; + return [NSArray arrayWithObjects:values count:count]; +} + +#pragma mark - Internal Methods + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { + if (!fields_) return; + size_t count = CFDictionaryGetCount(fields_); + ssize_t keys[count]; + GPBUnknownField *values[count]; + CFDictionaryGetKeysAndValues(fields_, (const void **)keys, + (const void **)values); + if (count > 1) { + struct GPBFieldPair { + ssize_t key; + GPBUnknownField *value; + } pairs[count]; + + for (size_t i = 0; i < count; ++i) { + pairs[i].key = keys[i]; + pairs[i].value = values[i]; + }; + qsort_b(pairs, count, sizeof(struct GPBFieldPair), + ^(const void *first, const void *second) { + const struct GPBFieldPair *a = first; + const struct GPBFieldPair *b = second; + return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); + }); + for (size_t i = 0; i < count; ++i) { + GPBUnknownField *value = pairs[i].value; + [value writeToOutput:output]; + } + } else { + [values[0] writeToOutput:output]; + } +} + +- (NSString *)description { + NSMutableString *description = [NSMutableString + stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self]; + NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" "); + [description appendString:textFormat]; + [description appendString:@"}"]; + return description; +} + +static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + size_t *result = context; + *result += [field serializedSize]; +} + +- (size_t)serializedSize { + size_t result = 0; + if (fields_) { + CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize, + &result); + } + return result; +} + +static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key, + const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + GPBCodedOutputStream *output = context; + [field writeAsMessageSetExtensionToOutput:output]; +} + +- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output { + if (fields_) { + CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo, + output); + } +} + +static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, + const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + size_t *result = context; + *result += [field serializedSizeAsMessageSetExtension]; +} + +- (size_t)serializedSizeAsMessageSet { + size_t result = 0; + if (fields_) { + CFDictionaryApplyFunction( + fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result); + } + return result; +} + +- (NSData *)data { + NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize]; + GPBCodedOutputStream *output = + [[GPBCodedOutputStream alloc] initWithData:data]; + [self writeToCodedOutputStream:output]; + [output release]; + return data; +} + ++ (BOOL)isFieldTag:(int32_t)tag { + return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; +} + +- (void)addField:(GPBUnknownField *)field { + int32_t number = [field number]; + checkNumber(number); + if (!fields_) { + // Use a custom dictionary here because the keys are numbers and conversion + // back and forth from NSNumber isn't worth the cost. + fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, + &kCFTypeDictionaryValueCallBacks); + } + ssize_t key = number; + CFDictionarySetValue(fields_, (const void *)key, field); +} + +- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { + ssize_t key = number; + GPBUnknownField *existing = + fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; + if (!existing && create) { + existing = [[GPBUnknownField alloc] initWithNumber:number]; + // This retains existing. + [self addField:existing]; + [existing release]; + } + return existing; +} + +static void GPBUnknownFieldSetMergeUnknownFields(const void *key, + const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + GPBUnknownFieldSet *self = context; + + int32_t number = [field number]; + checkNumber(number); + GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO]; + if (oldField) { + [oldField mergeFromField:field]; + } else { + // Merge only comes from GPBMessage's mergeFrom:, so it means we are on + // mutable message and are an mutable instance, so make sure we need + // mutable fields. + GPBUnknownField *fieldCopy = [field copy]; + [self addField:fieldCopy]; + [fieldCopy release]; + } +} + +- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other { + if (other && other->fields_) { + CFDictionaryApplyFunction(other->fields_, + GPBUnknownFieldSetMergeUnknownFields, self); + } +} + +- (void)mergeFromData:(NSData *)data { + GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; + [self mergeFromCodedInputStream:input]; + [input checkLastTagWas:0]; + [input release]; +} + +- (void)mergeVarintField:(int32_t)number value:(int32_t)value { + checkNumber(number); + [[self mutableFieldForNumber:number create:YES] addVarint:value]; +} + +- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { + NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag"); + int32_t number = GPBWireFormatGetTagFieldNumber(tag); + GPBCodedInputStreamState *state = &input->state_; + switch (GPBWireFormatGetTagWireType(tag)) { + case GPBWireFormatVarint: { + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addVarint:GPBCodedInputStreamReadInt64(state)]; + return YES; + } + case GPBWireFormatFixed64: { + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addFixed64:GPBCodedInputStreamReadFixed64(state)]; + return YES; + } + case GPBWireFormatLengthDelimited: { + NSData *data = GPBCodedInputStreamReadRetainedBytes(state); + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addLengthDelimited:data]; + [data release]; + return YES; + } + case GPBWireFormatStartGroup: { + GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; + [input readUnknownGroup:number message:unknownFieldSet]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addGroup:unknownFieldSet]; + [unknownFieldSet release]; + return YES; + } + case GPBWireFormatEndGroup: + return NO; + case GPBWireFormatFixed32: { + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; + return YES; + } + } +} + +- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData { + [[self mutableFieldForNumber:number create:YES] + addLengthDelimited:messageData]; +} + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { + GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; + [field addLengthDelimited:data]; +} + +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input { + while (YES) { + int32_t tag = GPBCodedInputStreamReadTag(&input->state_); + if (tag == 0 || ![self mergeFieldFrom:tag input:input]) { + break; + } + } +} + +- (void)getTags:(int32_t *)tags { + if (!fields_) return; + size_t count = CFDictionaryGetCount(fields_); + ssize_t keys[count]; + CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); + for (size_t i = 0; i < count; ++i) { + tags[i] = (int32_t)keys[i]; + } +} + +#pragma clang diagnostic pop + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet_PackagePrivate.h new file mode 100644 index 0000000..e27127a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet_PackagePrivate.h @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBUnknownFieldSet.h" + +@class GPBCodedOutputStream; +@class GPBCodedInputStream; + +@interface GPBUnknownFieldSet () + ++ (BOOL)isFieldTag:(int32_t)tag; + +- (NSData *)data; + +- (size_t)serializedSize; +- (size_t)serializedSizeAsMessageSet; + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output; +- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output; + +- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other; + +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input; +- (void)mergeFromData:(NSData *)data; + +- (void)mergeVarintField:(int32_t)number value:(int32_t)value; +- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input; +- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData; + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data; + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField_PackagePrivate.h new file mode 100644 index 0000000..2b4c789 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUnknownField_PackagePrivate.h @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBUnknownField.h" + +@class GPBCodedOutputStream; + +@interface GPBUnknownField () + +- (void)writeToOutput:(GPBCodedOutputStream *)output; +- (size_t)serializedSize; + +- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output; +- (size_t)serializedSizeAsMessageSetExtension; + +- (void)mergeFromField:(GPBUnknownField *)other; + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities.h new file mode 100644 index 0000000..5464dfb --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities.h @@ -0,0 +1,539 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBArray.h" +#import "GPBMessage.h" +#import "GPBRuntimeTypes.h" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +/** + * Generates a string that should be a valid "TextFormat" for the C++ version + * of Protocol Buffers. + * + * @param message The message to generate from. + * @param lineIndent A string to use as the prefix for all lines generated. Can + * be nil if no extra indent is needed. + * + * @return An NSString with the TextFormat of the message. + **/ +NSString *GPBTextFormatForMessage(GPBMessage *message, + NSString * __nullable lineIndent); + +/** + * Generates a string that should be a valid "TextFormat" for the C++ version + * of Protocol Buffers. + * + * @param unknownSet The unknown field set to generate from. + * @param lineIndent A string to use as the prefix for all lines generated. Can + * be nil if no extra indent is needed. + * + * @return An NSString with the TextFormat of the unknown field set. + **/ +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet * __nullable unknownSet, + NSString * __nullable lineIndent); + +/** + * Checks if the given field number is set on a message. + * + * @param self The message to check. + * @param fieldNumber The field number to check. + * + * @return YES if the field number is set on the given message. + **/ +BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber); + +/** + * Checks if the given field is set on a message. + * + * @param self The message to check. + * @param field The field to check. + * + * @return YES if the field is set on the given message. + **/ +BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Clears the given field for the given message. + * + * @param self The message for which to clear the field. + * @param field The field to clear. + **/ +void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); + +//%PDDM-EXPAND GPB_ACCESSORS() +// This block of code is generated, do not edit it directly. + + +// +// Get/Set a given field from/to a message. +// + +// Single Fields + +/** + * Gets the value of a bytes field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a bytes field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value); + +/** + * Gets the value of a string field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a string field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value); + +/** + * Gets the value of a message field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a message field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +/** + * Gets the value of a group field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a group field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +/** + * Gets the value of a bool field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a bool field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value); + +/** + * Gets the value of an int32 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an int32 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); + +/** + * Gets the value of an uint32 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an uint32 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value); + +/** + * Gets the value of an int64 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an int64 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value); + +/** + * Gets the value of an uint64 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an uint64 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value); + +/** + * Gets the value of a float field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a float field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value); + +/** + * Gets the value of a double field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a double field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value); + +/** + * Gets the given enum field of a message. For proto3, if the value isn't a + * member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned. + * GPBGetMessageRawEnumField will bypass the check and return whatever value + * was set. + * + * @param self The message from which to get the field. + * @param field The field to get. + * + * @return The enum value for the given field. + **/ +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Set the given enum field of a message. You can only set values that are + * members of the enum. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The enum value to set in the field. + **/ +void GPBSetMessageEnumField(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); + +/** + * Get the given enum field of a message. No check is done to ensure the value + * was defined in the enum. + * + * @param self The message from which to get the field. + * @param field The field to get. + * + * @return The raw enum value for the given field. + **/ +int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Set the given enum field of a message. You can set the value to anything, + * even a value that is not a member of the enum. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The raw enum value to set in the field. + **/ +void GPBSetMessageRawEnumField(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); + +// Repeated Fields + +/** + * Gets the value of a repeated field. + * + * @param self The message from which to get the field. + * @param field The repeated field to get. + * + * @return A GPB*Array or an NSMutableArray based on the field's type. + **/ +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a repeated field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param array A GPB*Array or NSMutableArray based on the field's type. + **/ +void GPBSetMessageRepeatedField(GPBMessage *self, + GPBFieldDescriptor *field, + id array); + +// Map Fields + +/** + * Gets the value of a map<> field. + * + * @param self The message from which to get the field. + * @param field The repeated field to get. + * + * @return A GPB*Dictionary or NSMutableDictionary based on the field's type. + **/ +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a map<> field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param dictionary A GPB*Dictionary or NSMutableDictionary based on the + * field's type. + **/ +void GPBSetMessageMapField(GPBMessage *self, + GPBFieldDescriptor *field, + id dictionary); + +//%PDDM-EXPAND-END GPB_ACCESSORS() + +/** + * Returns an empty NSData to assign to byte fields when you wish to assign them + * to empty. Prevents allocating a lot of little [NSData data] objects. + **/ +NSData *GPBEmptyNSData(void) __attribute__((pure)); + +/** + * Drops the `unknownFields` from the given message and from all sub message. + **/ +void GPBMessageDropUnknownFieldsRecursively(GPBMessage *message); + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + + +//%PDDM-DEFINE GPB_ACCESSORS() +//% +//%// +//%// Get/Set a given field from/to a message. +//%// +//% +//%// Single Fields +//% +//%GPB_ACCESSOR_SINGLE_FULL(Bytes, NSData, , *) +//%GPB_ACCESSOR_SINGLE_FULL(String, NSString, , *) +//%GPB_ACCESSOR_SINGLE_FULL(Message, GPBMessage, , *) +//%GPB_ACCESSOR_SINGLE_FULL(Group, GPBMessage, , *) +//%GPB_ACCESSOR_SINGLE(Bool, BOOL, ) +//%GPB_ACCESSOR_SINGLE(Int32, int32_t, n) +//%GPB_ACCESSOR_SINGLE(UInt32, uint32_t, n) +//%GPB_ACCESSOR_SINGLE(Int64, int64_t, n) +//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t, n) +//%GPB_ACCESSOR_SINGLE(Float, float, ) +//%GPB_ACCESSOR_SINGLE(Double, double, ) +//%/** +//% * Gets the given enum field of a message. For proto3, if the value isn't a +//% * member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned. +//% * GPBGetMessageRawEnumField will bypass the check and return whatever value +//% * was set. +//% * +//% * @param self The message from which to get the field. +//% * @param field The field to get. +//% * +//% * @return The enum value for the given field. +//% **/ +//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Set the given enum field of a message. You can only set values that are +//% * members of the enum. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param value The enum value to set in the field. +//% **/ +//%void GPBSetMessageEnumField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% int32_t value); +//% +//%/** +//% * Get the given enum field of a message. No check is done to ensure the value +//% * was defined in the enum. +//% * +//% * @param self The message from which to get the field. +//% * @param field The field to get. +//% * +//% * @return The raw enum value for the given field. +//% **/ +//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Set the given enum field of a message. You can set the value to anything, +//% * even a value that is not a member of the enum. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param value The raw enum value to set in the field. +//% **/ +//%void GPBSetMessageRawEnumField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% int32_t value); +//% +//%// Repeated Fields +//% +//%/** +//% * Gets the value of a repeated field. +//% * +//% * @param self The message from which to get the field. +//% * @param field The repeated field to get. +//% * +//% * @return A GPB*Array or an NSMutableArray based on the field's type. +//% **/ +//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Sets the value of a repeated field. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param array A GPB*Array or NSMutableArray based on the field's type. +//% **/ +//%void GPBSetMessageRepeatedField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% id array); +//% +//%// Map Fields +//% +//%/** +//% * Gets the value of a map<> field. +//% * +//% * @param self The message from which to get the field. +//% * @param field The repeated field to get. +//% * +//% * @return A GPB*Dictionary or NSMutableDictionary based on the field's type. +//% **/ +//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Sets the value of a map<> field. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param dictionary A GPB*Dictionary or NSMutableDictionary based on the +//% * field's type. +//% **/ +//%void GPBSetMessageMapField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% id dictionary); +//% + +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE, AN) +//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, ) +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, TisP) +//%/** +//% * Gets the value of a##AN NAME$L field. +//% * +//% * @param self The message from which to get the field. +//% * @param field The field to get. +//% **/ +//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Sets the value of a##AN NAME$L field. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param value The to set in the field. +//% **/ +//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value); +//% diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities.m new file mode 100644 index 0000000..0d3a080 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities.m @@ -0,0 +1,2214 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBUtilities_PackagePrivate.h" + +#import + +#import "GPBArray_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFieldSet.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +static void AppendTextFormatForMessage(GPBMessage *message, + NSMutableString *toStr, + NSString *lineIndent); + +// Are two datatypes the same basic type representation (ex Int32 and SInt32). +// Marked unused because currently only called from asserts/debug. +static BOOL DataTypesEquivalent(GPBDataType type1, + GPBDataType type2) __attribute__ ((unused)); + +// Basic type representation for a type (ex: for SInt32 it is Int32). +// Marked unused because currently only called from asserts/debug. +static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused)); + +// String name for a data type. +// Marked unused because currently only called from asserts/debug. +static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused)); + +NSData *GPBEmptyNSData(void) { + static dispatch_once_t onceToken; + static NSData *defaultNSData = nil; + dispatch_once(&onceToken, ^{ + defaultNSData = [[NSData alloc] init]; + }); + return defaultNSData; +} + +void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) { + if (!initialMessage) { + return; + } + + // Use an array as a list to process to avoid recursion. + NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage]; + + while (todo.count) { + GPBMessage *msg = todo.lastObject; + [todo removeLastObject]; + + // Clear unknowns. + msg.unknownFields = nil; + + // Handle the message fields. + GPBDescriptor *descriptor = [[msg class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (!GPBFieldDataTypeIsMessage(field)) { + continue; + } + switch (field.fieldType) { + case GPBFieldTypeSingle: + if (GPBGetHasIvarField(msg, field)) { + GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); + [todo addObject:fieldMessage]; + } + break; + + case GPBFieldTypeRepeated: { + NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); + if (fieldMessages.count) { + [todo addObjectsFromArray:fieldMessages]; + } + break; + } + + case GPBFieldTypeMap: { + id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); + switch (field.mapKeyDataType) { + case GPBDataTypeBool: + [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + BOOL key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + int32_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + int64_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeString: + [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:obj]; + }]; + break; + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeEnum: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + NSCAssert(NO, @"Aren't valid key types."); + } + break; + } // switch(field.mapKeyDataType) + } // switch(field.fieldType) + } // for(fields) + + // Handle any extensions holding messages. + for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) { + if (!GPBDataTypeIsMessage(extension.dataType)) { + continue; + } + if (extension.isRepeated) { + NSArray *extMessages = [msg getExtension:extension]; + [todo addObjectsFromArray:extMessages]; + } else { + GPBMessage *extMessage = [msg getExtension:extension]; + [todo addObject:extMessage]; + } + } // for(extensionsCurrentlySet) + + } // while(todo.count) +} + + +// -- About Version Checks -- +// There's actually 3 places these checks all come into play: +// 1. When the generated source is compile into .o files, the header check +// happens. This is checking the protoc used matches the library being used +// when making the .o. +// 2. Every place a generated proto header is included in a developer's code, +// the header check comes into play again. But this time it is checking that +// the current library headers being used still support/match the ones for +// the generated code. +// 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is +// called from the generated code passing in values captured when the +// generated code's .o was made. This checks that at runtime the generated +// code and runtime library match. + +void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) { + // NOTE: This is passing the value captured in the compiled code to check + // against the values captured when the runtime support was compiled. This + // ensures the library code isn't in a different framework/library that + // was generated with a non matching version. + if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) { + // Library is too old for headers. + [NSException raise:NSInternalInconsistencyException + format:@"Linked to ProtocolBuffer runtime version %d," + @" but code compiled needing atleast %d!", + GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion]; + } + if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { + // Headers are too old for library. + [NSException raise:NSInternalInconsistencyException + format:@"Proto generation source compiled against runtime" + @" version %d, but this version of the runtime only" + @" supports back to %d!", + objcRuntimeVersion, + GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION]; + } +} + +// This api is no longer used for version checks. 30001 is the last version +// using this old versioning model. When that support is removed, this function +// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h). +void GPBCheckRuntimeVersionInternal(int32_t version) { + GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001, + time_to_remove_this_old_version_shim); + if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { + [NSException raise:NSInternalInconsistencyException + format:@"Linked to ProtocolBuffer runtime version %d," + @" but code compiled with version %d!", + GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; + } +} + +BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { + GPBDescriptor *descriptor = [self descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; + return GPBMessageHasFieldSet(self, field); +} + +BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) { + if (self == nil || field == nil) return NO; + + // Repeated/Map don't use the bit, they check the count. + if (GPBFieldIsMapOrArray(field)) { + // Array/map type doesn't matter, since GPB*Array/NSArray and + // GPB*Dictionary/NSDictionary all support -count; + NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + return (arrayOrMap.count > 0); + } else { + return GPBGetHasIvarField(self, field); + } +} + +void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { + // If not set, nothing to do. + if (!GPBGetHasIvarField(self, field)) { + return; + } + + if (GPBFieldStoresObject(field)) { + // Object types are handled slightly differently, they need to be released. + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + [*typePtr release]; + *typePtr = nil; + } else { + // POD types just need to clear the has bit as the Get* method will + // fetch the default when needed. + } + GPBSetHasIvarField(self, field, NO); +} + +BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); + if (idx < 0) { + NSCAssert(fieldNumber != 0, @"Invalid field number."); + BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber); + return hasIvar; + } else { + NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); + uint32_t byteIndex = idx / 32; + uint32_t bitMask = (1U << (idx % 32)); + BOOL hasIvar = + (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO; + return hasIvar; + } +} + +uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) { + NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", + [self class], idx); + uint32_t result = self->messageStorage_->_has_storage_[-idx]; + return result; +} + +void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, + BOOL value) { + if (idx < 0) { + NSCAssert(fieldNumber != 0, @"Invalid field number."); + uint32_t *has_storage = self->messageStorage_->_has_storage_; + has_storage[-idx] = (value ? fieldNumber : 0); + } else { + NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); + uint32_t *has_storage = self->messageStorage_->_has_storage_; + uint32_t byte = idx / 32; + uint32_t bitMask = (1U << (idx % 32)); + if (value) { + has_storage[byte] |= bitMask; + } else { + has_storage[byte] &= ~bitMask; + } + } +} + +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { + uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); + if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { + // Do nothing/nothing set in the oneof. + return; + } + + // Like GPBClearMessageField(), free the memory if an objecttype is set, + // pod types don't need to do anything. + GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet]; + NSCAssert(fieldSet, + @"%@: oneof set to something (%u) not in the oneof?", + [self class], fieldNumberSet); + if (fieldSet && GPBFieldStoresObject(fieldSet)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[fieldSet->description_->offset]; + [*typePtr release]; + *typePtr = nil; + } + + // Set to nothing stored in the oneof. + // (field number doesn't matter since setting to nothing). + GPBSetHasIvar(self, oneofHasIndex, 1, NO); +} + +#pragma mark - IVar accessors + +//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) +//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% if (GPBGetHasIvarField(self, field)) { +//% uint8_t *storage = (uint8_t *)self->messageStorage_; +//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; +//% return *typePtr; +//% } else { +//% return field.defaultValue.value##NAME; +//% } +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value) { +//% if (self == nil || field == nil) return; +//% GPBFileSyntax syntax = [self descriptor].file.syntax; +//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); +//%} +//% +//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value, +//% NAME$S GPBFileSyntax syntax) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBOneofDescriptor *oneof = field->containingOneof_; +//% if (oneof) { +//% GPBMessageFieldDescription *fieldDesc = field->description_; +//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); +//% } +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(self->messageStorage_ != NULL, +//% @"%@: All messages should have storage (from init)", +//% [self class]); +//%#endif +//%#if defined(__clang_analyzer__) +//% if (self->messageStorage_ == NULL) return; +//%#endif +//% uint8_t *storage = (uint8_t *)self->messageStorage_; +//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; +//% *typePtr = value; +//% // proto2: any value counts as having been set; proto3, it +//% // has to be a non zero value or be in a oneof. +//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2) +//% || (value != (TYPE)0) +//% || (field->containingOneof_ != NULL)); +//% GPBSetHasIvarField(self, field, hasValue); +//% GPBBecomeVisibleToAutocreator(self); +//%} +//% +//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE) +//%// Only exists for public api, no core code should use this. +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% return (TYPE *)GPBGetObjectIvarWithField(self, field); +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBSetObjectIvarWithField(self, field, (id)value); +//%} +//% +//%PDDM-DEFINE IVAR_ALIAS_DEFN_COPY_OBJECT(NAME, TYPE) +//%// Only exists for public api, no core code should use this. +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% return (TYPE *)GPBGetObjectIvarWithField(self, field); +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBSetCopyObjectIvarWithField(self, field, (id)value); +//%} +//% + +// Object types are handled slightly differently, they need to be released +// and retained. + +void GPBSetAutocreatedRetainedObjectIvarWithField( + GPBMessage *self, GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) value) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once."); + *typePtr = value; +} + +void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field) { + if (GPBGetHasIvarField(self, field)) { + return; + } + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + GPBMessage *oldValue = *typePtr; + *typePtr = NULL; + GPBClearMessageAutocreator(oldValue); + [oldValue release]; +} + +// This exists only for briging some aliased types, nothing else should use it. +static void GPBSetObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], + syntax); +} + +static void GPBSetCopyObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value); + +// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags +// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldInternal +// is marked as consuming the value. Note: For some reason this doesn't happen +// with the -retain in GPBSetObjectIvarWithField. +#if !defined(__clang_analyzer__) +// This exists only for briging some aliased types, nothing else should use it. +static void GPBSetCopyObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value copy], + syntax); +} +#endif // !defined(__clang_analyzer__) + +void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, id value, + GPBFileSyntax syntax) { + GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], + syntax); +} + +void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + id value, GPBFileSyntax syntax) { + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + GPBDataType fieldType = GPBGetFieldDataType(field); + BOOL isMapOrArray = GPBFieldIsMapOrArray(field); + BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); +#if defined(DEBUG) && DEBUG + if (value == nil && !isMapOrArray && !fieldIsMessage && + field.hasDefaultValue) { + // Setting a message to nil is an obvious way to "clear" the value + // as there is no way to set a non-empty default value for messages. + // + // For Strings and Bytes that have default values set it is not clear what + // should be done when their value is set to nil. Is the intention just to + // clear the set value and reset to default, or is the intention to set the + // value to the empty string/data? Arguments can be made for both cases. + // 'nil' has been abused as a replacement for an empty string/data in ObjC. + // We decided to be consistent with all "object" types and clear the has + // field, and fall back on the default value. The warning below will only + // appear in debug, but the could should be changed so the intention is + // clear. + NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_); + NSString *propName = field.name; + NSString *className = self.descriptor.name; + NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with " + @"default values. Please use '%@.%@ = %@' if you want to set it to " + @"empty, or call '%@.%@ = NO' to reset it to it's default value of " + @"'%@'. Defaulting to resetting default value.", + className, propName, className, propName, + (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", + className, hasSel, field.defaultValue.valueString); + // Note: valueString, depending on the type, it could easily be + // valueData/valueMessage. + } +#endif // DEBUG + if (!isMapOrArray) { + // Non repeated/map can be in an oneof, clear any existing value from the + // oneof. + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } + // Clear "has" if they are being set to nil. + BOOL setHasValue = (value != nil); + // Under proto3, Bytes & String fields get cleared by resetting them to + // their default (empty) values, so if they are set to something of length + // zero, they are being cleared. + if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && + ([value length] == 0)) { + // Except, if the field was in a oneof, then it still gets recorded as + // having been set so the state of the oneof can be serialized back out. + if (!oneof) { + setHasValue = NO; + } + if (setHasValue) { + NSCAssert(value != nil, @"Should never be setting has for nil"); + } else { + // The value passed in was retained, it must be released since we + // aren't saving anything in the field. + [value release]; + value = nil; + } + } + GPBSetHasIvarField(self, field, setHasValue); + } + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + + id oldValue = *typePtr; + + *typePtr = value; + + if (oldValue) { + if (isMapOrArray) { + if (field.fieldType == GPBFieldTypeRepeated) { + // If the old array was autocreated by us, then clear it. + if (GPBDataTypeIsObject(fieldType)) { + if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) { + GPBAutocreatedArray *autoArray = oldValue; + if (autoArray->_autocreator == self) { + autoArray->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Array. + GPBInt32Array *gpbArray = oldValue; + if (gpbArray->_autocreator == self) { + gpbArray->_autocreator = nil; + } + } + } else { // GPBFieldTypeMap + // If the old map was autocreated by us, then clear it. + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(fieldType)) { + if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) { + GPBAutocreatedDictionary *autoDict = oldValue; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Dictionary. + GPBInt32Int32Dictionary *gpbDict = oldValue; + if (gpbDict->_autocreator == self) { + gpbDict->_autocreator = nil; + } + } + } + } else if (fieldIsMessage) { + // If the old message value was autocreated by us, then clear it. + GPBMessage *oldMessageValue = oldValue; + if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) { + GPBClearMessageAutocreator(oldMessageValue); + } + } + [oldValue release]; + } + + GPBBecomeVisibleToAutocreator(self); +} + +id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, + GPBFieldDescriptor *field) { + if (self->messageStorage_ == nil) { + return nil; + } + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + return *typePtr; +} + +// Only exists for public api, no core code should use this. +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + return GPBGetEnumIvarWithFieldInternal(self, field, syntax); +} + +int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to get value of type Enum from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + int32_t result = GPBGetMessageInt32Field(self, field); + // If this is presevering unknown enums, make sure the value is valid before + // returning it. + if (GPBHasPreservingUnknownEnumSemantics(syntax) && + ![field isValidEnumValue:result]) { + result = kGPBUnrecognizedEnumeratorValue; + } + return result; +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, int32_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type Enum.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + // Don't allow in unknown values. Proto3 can use the Raw method. + if (![field isValidEnumValue:value]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Attempt to set an unknown enum value (%d)", + [self class], field.name, value]; + } + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +// Only exists for public api, no core code should use this. +int32_t GPBGetMessageRawEnumField(GPBMessage *self, + GPBFieldDescriptor *field) { + int32_t result = GPBGetMessageInt32Field(self, field); + return result; +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +BOOL GPBGetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to get value of type bool from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + // Bools are stored in the has bits to avoid needing explicit space in the + // storage structure. + // (the field number passed to the HasIvar helper doesn't really matter + // since the offset is never negative) + GPBMessageFieldDescription *fieldDesc = field->description_; + return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number); + } else { + return field.defaultValue.valueBool; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type bool.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } + + // Bools are stored in the has bits to avoid needing explicit space in the + // storage structure. + // (the field number passed to the HasIvar helper doesn't really matter since + // the offset is never negative) + GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value); + + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (BOOL)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +int32_t GPBGetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt32), + @"Attempting to get value of int32_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueInt32; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt32), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type int32_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (int32_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt32), + @"Attempting to get value of uint32_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueUInt32; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt32), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type uint32_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (uint32_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +int64_t GPBGetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt64), + @"Attempting to get value of int64_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueInt64; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt64), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type int64_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (int64_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt64), + @"Attempting to get value of uint64_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueUInt64; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt64), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type uint64_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (uint64_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float) +// This block of code is generated, do not edit it directly. + +float GPBGetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeFloat), + @"Attempting to get value of float from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + float *typePtr = (float *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueFloat; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field, + float value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + float value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeFloat), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type float.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + float *typePtr = (float *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (float)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double) +// This block of code is generated, do not edit it directly. + +double GPBGetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeDouble), + @"Attempting to get value of double from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + double *typePtr = (double *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueDouble; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field, + double value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + double value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeDouble), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type double.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + double *typePtr = (double *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (double)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND-END (6 expansions) + +// Aliases are function calls that are virtually the same. + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +NSString *GPBGetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeString), + @"Attempting to get value of NSString from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (NSString *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field, + NSString *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeString), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type NSString.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetCopyObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +NSData *GPBGetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeBytes), + @"Attempting to get value of NSData from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (NSData *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field, + NSData *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeBytes), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type NSData.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetCopyObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeMessage), + @"Attempting to get value of GPBMessage from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageMessageField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBMessage *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeMessage), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type GPBMessage.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeGroup), + @"Attempting to get value of GPBMessage from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageGroupField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBMessage *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeGroup), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type GPBMessage.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND-END (4 expansions) + +// GPBGetMessageRepeatedField is defined in GPBMessage.m + +// Only exists for public api, no core code should use this. +void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } + Class expectedClass = Nil; + switch (GPBGetFieldDataType(field)) { + case GPBDataTypeBool: + expectedClass = [GPBBoolArray class]; + break; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + expectedClass = [GPBInt32Array class]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + expectedClass = [GPBUInt32Array class]; + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + expectedClass = [GPBInt64Array class]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + expectedClass = [GPBUInt64Array class]; + break; + case GPBDataTypeFloat: + expectedClass = [GPBFloatArray class]; + break; + case GPBDataTypeDouble: + expectedClass = [GPBDoubleArray class]; + break; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + expectedClass = [NSMutableArray class]; + break; + case GPBDataTypeEnum: + expectedClass = [GPBEnumArray class]; + break; + } + if (array && ![array isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, [array class]]; + } +#endif + GPBSetObjectIvarWithField(self, field, array); +} + +static GPBDataType BaseDataType(GPBDataType type) { + switch (type) { + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + return GPBDataTypeInt32; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return GPBDataTypeUInt32; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return GPBDataTypeInt64; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return GPBDataTypeUInt64; + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return GPBDataTypeMessage; + case GPBDataTypeBool: + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeBytes: + case GPBDataTypeString: + return type; + } +} + +static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) { + return BaseDataType(type1) == BaseDataType(type2); +} + +static NSString *TypeToString(GPBDataType dataType) { + switch (dataType) { + case GPBDataTypeBool: + return @"Bool"; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + return @"Int32"; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return @"UInt32"; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return @"Int64"; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return @"UInt64"; + case GPBDataTypeFloat: + return @"Float"; + case GPBDataTypeDouble: + return @"Double"; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return @"Object"; + case GPBDataTypeEnum: + return @"Enum"; + } +} + +// GPBGetMessageMapField is defined in GPBMessage.m + +// Only exists for public api, no core code should use this. +void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, + id dictionary) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } + if (dictionary) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSString *keyStr = TypeToString(keyDataType); + NSString *valueStr = TypeToString(valueDataType); + if (keyDataType == GPBDataTypeString) { + keyStr = @"String"; + } + Class expectedClass = Nil; + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + expectedClass = [NSMutableDictionary class]; + } else { + NSString *className = + [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr]; + expectedClass = NSClassFromString(className); + NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass); + } + if (![dictionary isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, + [dictionary class]]; + } + } +#endif + GPBSetObjectIvarWithField(self, field, dictionary); +} + +#pragma mark - Misc Dynamic Runtime Utils + +const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { + Protocol *protocol = + objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol)); + NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol"); + struct objc_method_description description = + protocol_getMethodDescription(protocol, selector, NO, instanceSel); + NSCAssert(description.name != Nil && description.types != nil, + @"Missing method for selector %@", NSStringFromSelector(selector)); + return description.types; +} + +#pragma mark - Text Format Support + +static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) { + [destStr appendString:@"\""]; + NSUInteger len = [toPrint length]; + for (NSUInteger i = 0; i < len; ++i) { + unichar aChar = [toPrint characterAtIndex:i]; + switch (aChar) { + case '\n': [destStr appendString:@"\\n"]; break; + case '\r': [destStr appendString:@"\\r"]; break; + case '\t': [destStr appendString:@"\\t"]; break; + case '\"': [destStr appendString:@"\\\""]; break; + case '\'': [destStr appendString:@"\\\'"]; break; + case '\\': [destStr appendString:@"\\\\"]; break; + default: + // This differs slightly from the C++ code in that the C++ doesn't + // generate UTF8; it looks at the string in UTF8, but escapes every + // byte > 0x7E. + if (aChar < 0x20) { + [destStr appendFormat:@"\\%d%d%d", + (aChar / 64), ((aChar % 64) / 8), (aChar % 8)]; + } else { + [destStr appendFormat:@"%C", aChar]; + } + break; + } + } + [destStr appendString:@"\""]; +} + +static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) { + const char *src = (const char *)[buffer bytes]; + size_t srcLen = [buffer length]; + [destStr appendString:@"\""]; + for (const char *srcEnd = src + srcLen; src < srcEnd; src++) { + switch (*src) { + case '\n': [destStr appendString:@"\\n"]; break; + case '\r': [destStr appendString:@"\\r"]; break; + case '\t': [destStr appendString:@"\\t"]; break; + case '\"': [destStr appendString:@"\\\""]; break; + case '\'': [destStr appendString:@"\\\'"]; break; + case '\\': [destStr appendString:@"\\\\"]; break; + default: + if (isprint(*src)) { + [destStr appendFormat:@"%c", *src]; + } else { + // NOTE: doing hex means you have to worry about the letter after + // the hex being another hex char and forcing that to be escaped, so + // use octal to keep it simple. + [destStr appendFormat:@"\\%03o", (uint8_t)(*src)]; + } + break; + } + } + [destStr appendString:@"\""]; +} + +static void AppendTextFormatForMapMessageField( + id map, GPBFieldDescriptor *field, NSMutableString *toStr, + NSString *lineIndent, NSString *fieldName, NSString *lineEnding) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType); + + NSString *msgStartFirst = + [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding]; + NSString *msgStart = + [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName]; + NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent]; + + NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent]; + NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent, + (isMessageValue ? "" : ":")]; + + __block BOOL isFirst = YES; + + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + // map is an NSDictionary. + NSDictionary *dict = map; + [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { + #pragma unused(stop) + [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; + isFirst = NO; + + [toStr appendString:keyLine]; + AppendStringEscaped(key, toStr); + [toStr appendString:@"\n"]; + + [toStr appendString:valueLine]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (valueDataType) { + case GPBDataTypeString: + AppendStringEscaped(value, toStr); + break; + + case GPBDataTypeBytes: + AppendBufferAsString(value, toStr); + break; + + case GPBDataTypeMessage: + [toStr appendString:@"{\n"]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(value, toStr, subIndent); + [toStr appendFormat:@"%@ }", lineIndent]; + break; + + default: + NSCAssert(NO, @"Can't happen"); + break; + } +#pragma clang diagnostic pop + [toStr appendString:@"\n"]; + + [toStr appendString:msgEnd]; + }]; + } else { + // map is one of the GPB*Dictionary classes, type doesn't matter. + GPBInt32Int32Dictionary *dict = map; + [dict enumerateForTextFormat:^(id keyObj, id valueObj) { + [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; + isFirst = NO; + + // Key always is a NSString. + if (keyDataType == GPBDataTypeString) { + [toStr appendString:keyLine]; + AppendStringEscaped(keyObj, toStr); + [toStr appendString:@"\n"]; + } else { + [toStr appendFormat:@"%@%@\n", keyLine, keyObj]; + } + + [toStr appendString:valueLine]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (valueDataType) { + case GPBDataTypeString: + AppendStringEscaped(valueObj, toStr); + break; + + case GPBDataTypeBytes: + AppendBufferAsString(valueObj, toStr); + break; + + case GPBDataTypeMessage: + [toStr appendString:@"{\n"]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(valueObj, toStr, subIndent); + [toStr appendFormat:@"%@ }", lineIndent]; + break; + + case GPBDataTypeEnum: { + int32_t enumValue = [valueObj intValue]; + NSString *valueStr = nil; + GPBEnumDescriptor *descriptor = field.enumDescriptor; + if (descriptor) { + valueStr = [descriptor textFormatNameForValue:enumValue]; + } + if (valueStr) { + [toStr appendString:valueStr]; + } else { + [toStr appendFormat:@"%d", enumValue]; + } + break; + } + + default: + NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen"); + // Everything else is a NSString. + [toStr appendString:valueObj]; + break; + } +#pragma clang diagnostic pop + [toStr appendString:@"\n"]; + + [toStr appendString:msgEnd]; + }]; + } +} + +static void AppendTextFormatForMessageField(GPBMessage *message, + GPBFieldDescriptor *field, + NSMutableString *toStr, + NSString *lineIndent) { + id arrayOrMap; + NSUInteger count; + GPBFieldType fieldType = field.fieldType; + switch (fieldType) { + case GPBFieldTypeSingle: + arrayOrMap = nil; + count = (GPBGetHasIvarField(message, field) ? 1 : 0); + break; + + case GPBFieldTypeRepeated: + // Will be NSArray or GPB*Array, type doesn't matter, they both + // implement count. + arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); + count = [(NSArray *)arrayOrMap count]; + break; + + case GPBFieldTypeMap: { + // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter, + // they both implement count. + arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); + count = [(NSDictionary *)arrayOrMap count]; + break; + } + } + + if (count == 0) { + // Nothing to print, out of here. + return; + } + + NSString *lineEnding = @""; + + // If the name can't be reversed or support for extra info was turned off, + // this can return nil. + NSString *fieldName = [field textFormatName]; + if ([fieldName length] == 0) { + fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)]; + // If there is only one entry, put the objc name as a comment, other wise + // add it before the repeated values. + if (count > 1) { + [toStr appendFormat:@"%@# %@\n", lineIndent, field.name]; + } else { + lineEnding = [NSString stringWithFormat:@" # %@", field.name]; + } + } + + if (fieldType == GPBFieldTypeMap) { + AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, + fieldName, lineEnding); + return; + } + + id array = arrayOrMap; + const BOOL isRepeated = (array != nil); + + GPBDataType fieldDataType = GPBGetFieldDataType(field); + BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType); + for (NSUInteger j = 0; j < count; ++j) { + // Start the line. + [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, + (isMessageField ? "" : ":")]; + + // The value. + switch (fieldDataType) { +#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \ + : GPBGetMessage##REAL_TYPE##Field(message, field)); \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ + } + + FIELD_CASE(Int32, int32_t, Int32, @"%d") + FIELD_CASE(SInt32, int32_t, Int32, @"%d") + FIELD_CASE(SFixed32, int32_t, Int32, @"%d") + FIELD_CASE(UInt32, uint32_t, UInt32, @"%u") + FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u") + FIELD_CASE(Int64, int64_t, Int64, @"%lld") + FIELD_CASE(SInt64, int64_t, Int64, @"%lld") + FIELD_CASE(SFixed64, int64_t, Int64, @"%lld") + FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu") + FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu") + FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG) + FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG) + +#undef FIELD_CASE + + case GPBDataTypeEnum: { + int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j] + : GPBGetMessageInt32Field(message, field)); + NSString *valueStr = nil; + GPBEnumDescriptor *descriptor = field.enumDescriptor; + if (descriptor) { + valueStr = [descriptor textFormatNameForValue:v]; + } + if (valueStr) { + [toStr appendString:valueStr]; + } else { + [toStr appendFormat:@"%d", v]; + } + break; + } + + case GPBDataTypeBool: { + BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j] + : GPBGetMessageBoolField(message, field)); + [toStr appendString:(v ? @"true" : @"false")]; + break; + } + + case GPBDataTypeString: { + NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] + : GPBGetMessageStringField(message, field)); + AppendStringEscaped(v, toStr); + break; + } + + case GPBDataTypeBytes: { + NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] + : GPBGetMessageBytesField(message, field)); + AppendBufferAsString(v, toStr); + break; + } + + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + GPBMessage *v = + (isRepeated ? [(NSArray *)array objectAtIndex:j] + : GPBGetObjectIvarWithField(message, field)); + [toStr appendFormat:@"{%@\n", lineEnding]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(v, toStr, subIndent); + [toStr appendFormat:@"%@}", lineIndent]; + lineEnding = @""; + break; + } + + } // switch(fieldDataType) + + // End the line. + [toStr appendFormat:@"%@\n", lineEnding]; + + } // for(count) +} + +static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, + NSArray *activeExtensions, + GPBExtensionRange range, + NSMutableString *toStr, + NSString *lineIndent) { + uint32_t start = range.start; + uint32_t end = range.end; + for (GPBExtensionDescriptor *extension in activeExtensions) { + uint32_t fieldNumber = extension.fieldNumber; + if (fieldNumber < start) { + // Not there yet. + continue; + } + if (fieldNumber >= end) { + // Done. + break; + } + + id rawExtValue = [message getExtension:extension]; + BOOL isRepeated = extension.isRepeated; + + NSUInteger numValues = 1; + NSString *lineEnding = @""; + if (isRepeated) { + numValues = [(NSArray *)rawExtValue count]; + } + + NSString *singletonName = extension.singletonName; + if (numValues == 1) { + lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName]; + } else { + [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName]; + } + + GPBDataType extDataType = extension.dataType; + for (NSUInteger j = 0; j < numValues; ++j) { + id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue); + + // Start the line. + [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber, + (GPBDataTypeIsMessage(extDataType) ? "" : ":")]; + + // The value. + switch (extDataType) { +#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ + } + + FIELD_CASE(Int32, int32_t, intValue, @"%d") + FIELD_CASE(SInt32, int32_t, intValue, @"%d") + FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d") + FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u") + FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u") + FIELD_CASE(Int64, int64_t, longLongValue, @"%lld") + FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld") + FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld") + FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu") + FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu") + FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG) + FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG) + // TODO: Add a comment with the enum name from enum descriptors + // (might not be real value, so leave it as a comment, ObjC compiler + // name mangles differently). Doesn't look like we actually generate + // an enum descriptor reference like we do for normal fields, so this + // will take a compiler change. + FIELD_CASE(Enum, int32_t, intValue, @"%d") + +#undef FIELD_CASE + + case GPBDataTypeBool: + [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" + : @"false")]; + break; + + case GPBDataTypeString: + AppendStringEscaped(curValue, toStr); + break; + + case GPBDataTypeBytes: + AppendBufferAsString((NSData *)curValue, toStr); + break; + + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + [toStr appendFormat:@"{%@\n", lineEnding]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(curValue, toStr, subIndent); + [toStr appendFormat:@"%@}", lineIndent]; + lineEnding = @""; + break; + } + + } // switch(extDataType) + + // End the line. + [toStr appendFormat:@"%@\n", lineEnding]; + + } // for(numValues) + + } // for..in(activeExtensions) +} + +static void AppendTextFormatForMessage(GPBMessage *message, + NSMutableString *toStr, + NSString *lineIndent) { + GPBDescriptor *descriptor = [message descriptor]; + NSArray *fieldsArray = descriptor->fields_; + NSUInteger fieldCount = fieldsArray.count; + const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; + NSUInteger extensionRangesCount = descriptor.extensionRangesCount; + NSArray *activeExtensions = [[message extensionsCurrentlySet] + sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; + for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { + if (i == fieldCount) { + AppendTextFormatForMessageExtensionRange( + message, activeExtensions, extensionRanges[j++], toStr, lineIndent); + } else if (j == extensionRangesCount || + GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { + AppendTextFormatForMessageField(message, fieldsArray[i++], toStr, + lineIndent); + } else { + AppendTextFormatForMessageExtensionRange( + message, activeExtensions, extensionRanges[j++], toStr, lineIndent); + } + } + + NSString *unknownFieldsStr = + GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent); + if ([unknownFieldsStr length] > 0) { + [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent]; + [toStr appendString:unknownFieldsStr]; + } +} + +NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { + if (message == nil) return @""; + if (lineIndent == nil) lineIndent = @""; + + NSMutableString *buildString = [NSMutableString string]; + AppendTextFormatForMessage(message, buildString, lineIndent); + return buildString; +} + +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, + NSString *lineIndent) { + if (unknownSet == nil) return @""; + if (lineIndent == nil) lineIndent = @""; + + NSMutableString *result = [NSMutableString string]; + for (GPBUnknownField *field in [unknownSet sortedFields]) { + int32_t fieldNumber = [field number]; + +#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ + [field.PROPNAME \ + enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \ + _Pragma("unused(idx, stop)"); \ + [result \ + appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \ + }]; + + PRINT_LOOP(varintList, uint64_t, %llu); + PRINT_LOOP(fixed32List, uint32_t, 0x%X); + PRINT_LOOP(fixed64List, uint64_t, 0x%llX); + +#undef PRINT_LOOP + + // NOTE: C++ version of TextFormat tries to parse this as a message + // and print that if it succeeds. + for (NSData *data in field.lengthDelimitedList) { + [result appendFormat:@"%@%d: ", lineIndent, fieldNumber]; + AppendBufferAsString(data, result); + [result appendString:@"\n"]; + } + + for (GPBUnknownFieldSet *subUnknownSet in field.groupList) { + [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + NSString *subUnknwonSetStr = + GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent); + [result appendString:subUnknwonSetStr]; + [result appendFormat:@"%@}\n", lineIndent]; + } + } + return result; +} + +// Helpers to decode a varint. Not using GPBCodedInputStream version because +// that needs a state object, and we don't want to create an input stream out +// of the data. +GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) { + int8_t result = *((int8_t *)(*data)); + ++(*data); + return result; +} + +static int32_t ReadRawVarint32FromData(const uint8_t **data) { + int8_t tmp = ReadRawByteFromData(data); + if (tmp >= 0) { + return tmp; + } + int32_t result = tmp & 0x7f; + if ((tmp = ReadRawByteFromData(data)) >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = ReadRawByteFromData(data)) >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = ReadRawByteFromData(data)) >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = ReadRawByteFromData(data)) << 28; + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) { + if (ReadRawByteFromData(data) >= 0) { + return result; + } + } + [NSException raise:NSParseErrorException + format:@"Unable to read varint32"]; + } + } + } + } + return result; +} + +NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, + NSString *inputStr) { + // decodData form: + // varint32: num entries + // for each entry: + // varint32: key + // bytes*: decode data + // + // decode data one of two forms: + // 1: a \0 followed by the string followed by an \0 + // 2: bytecodes to transform an input into the right thing, ending with \0 + // + // the bytes codes are of the form: + // 0xabbccccc + // 0x0 (all zeros), end. + // a - if set, add an underscore + // bb - 00 ccccc bytes as is + // bb - 10 ccccc upper first, as is on rest, ccccc byte total + // bb - 01 ccccc lower first, as is on rest, ccccc byte total + // bb - 11 ccccc all upper, ccccc byte total + + if (!decodeData || !inputStr) { + return nil; + } + + // Find key + const uint8_t *scan = decodeData; + int32_t numEntries = ReadRawVarint32FromData(&scan); + BOOL foundKey = NO; + while (!foundKey && (numEntries > 0)) { + --numEntries; + int32_t dataKey = ReadRawVarint32FromData(&scan); + if (dataKey == key) { + foundKey = YES; + } else { + // If it is a inlined string, it will start with \0; if it is bytecode it + // will start with a code. So advance one (skipping the inline string + // marker), and then loop until reaching the end marker (\0). + ++scan; + while (*scan != 0) ++scan; + // Now move past the end marker. + ++scan; + } + } + + if (!foundKey) { + return nil; + } + + // Decode + + if (*scan == 0) { + // Inline string. Move over the marker, and NSString can take it as + // UTF8. + ++scan; + NSString *result = [NSString stringWithUTF8String:(const char *)scan]; + return result; + } + + NSMutableString *result = + [NSMutableString stringWithCapacity:[inputStr length]]; + + const uint8_t kAddUnderscore = 0b10000000; + const uint8_t kOpMask = 0b01100000; + // const uint8_t kOpAsIs = 0b00000000; + const uint8_t kOpFirstUpper = 0b01000000; + const uint8_t kOpFirstLower = 0b00100000; + const uint8_t kOpAllUpper = 0b01100000; + const uint8_t kSegmentLenMask = 0b00011111; + + NSInteger i = 0; + for (; *scan != 0; ++scan) { + if (*scan & kAddUnderscore) { + [result appendString:@"_"]; + } + int segmentLen = *scan & kSegmentLenMask; + uint8_t decodeOp = *scan & kOpMask; + + // Do op specific handling of the first character. + if (decodeOp == kOpFirstUpper) { + unichar c = [inputStr characterAtIndex:i]; + [result appendFormat:@"%c", toupper((char)c)]; + ++i; + --segmentLen; + } else if (decodeOp == kOpFirstLower) { + unichar c = [inputStr characterAtIndex:i]; + [result appendFormat:@"%c", tolower((char)c)]; + ++i; + --segmentLen; + } + // else op == kOpAsIs || op == kOpAllUpper + + // Now pull over the rest of the length for this segment. + for (int x = 0; x < segmentLen; ++x) { + unichar c = [inputStr characterAtIndex:(i + x)]; + if (decodeOp == kOpAllUpper) { + [result appendFormat:@"%c", toupper((char)c)]; + } else { + [result appendFormat:@"%C", c]; + } + } + i += segmentLen; + } + + return result; +} + +#pragma clang diagnostic pop + +BOOL GPBClassHasSel(Class aClass, SEL sel) { + // NOTE: We have to use class_copyMethodList, all other runtime method + // lookups actually also resolve the method implementation and this + // is called from within those methods. + + BOOL result = NO; + unsigned int methodCount = 0; + Method *methodList = class_copyMethodList(aClass, &methodCount); + for (unsigned int i = 0; i < methodCount; ++i) { + SEL methodSelector = method_getName(methodList[i]); + if (methodSelector == sel) { + result = YES; + break; + } + } + free(methodList); + return result; +} diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities_PackagePrivate.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities_PackagePrivate.h new file mode 100644 index 0000000..ed424ce --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBUtilities_PackagePrivate.h @@ -0,0 +1,351 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBUtilities.h" + +#import "GPBDescriptor_PackagePrivate.h" + +// Macros for stringifying library symbols. These are used in the generated +// PB descriptor classes wherever a library symbol name is represented as a +// string. See README.google for more information. +#define GPBStringify(S) #S +#define GPBStringifySymbol(S) GPBStringify(S) + +#define GPBNSStringify(S) @#S +#define GPBNSStringifySymbol(S) GPBNSStringify(S) + +// Constant to internally mark when there is no has bit. +#define GPBNoHasBit INT32_MAX + +CF_EXTERN_C_BEGIN + +// These two are used to inject a runtime check for version mismatch into the +// generated sources to make sure they are linked with a supporting runtime. +void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion); +GPB_INLINE void GPB_DEBUG_CHECK_RUNTIME_VERSIONS() { + // NOTE: By being inline here, this captures the value from the library's + // headers at the time the generated code was compiled. +#if defined(DEBUG) && DEBUG + GPBCheckRuntimeVersionSupport(GOOGLE_PROTOBUF_OBJC_VERSION); +#endif +} + +// Legacy version of the checks, remove when GOOGLE_PROTOBUF_OBJC_GEN_VERSION +// goes away (see more info in GPBBootstrap.h). +void GPBCheckRuntimeVersionInternal(int32_t version); +GPB_INLINE void GPBDebugCheckRuntimeVersion() { +#if defined(DEBUG) && DEBUG + GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION); +#endif +} + +// Conversion functions for de/serializing floating point types. + +GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) { + union { double f; int64_t i; } u; + u.f = v; + return u.i; +} + +GPB_INLINE int32_t GPBConvertFloatToInt32(float v) { + union { float f; int32_t i; } u; + u.f = v; + return u.i; +} + +GPB_INLINE double GPBConvertInt64ToDouble(int64_t v) { + union { double f; int64_t i; } u; + u.i = v; + return u.f; +} + +GPB_INLINE float GPBConvertInt32ToFloat(int32_t v) { + union { float f; int32_t i; } u; + u.i = v; + return u.f; +} + +GPB_INLINE int32_t GPBLogicalRightShift32(int32_t value, int32_t spaces) { + return (int32_t)((uint32_t)(value) >> spaces); +} + +GPB_INLINE int64_t GPBLogicalRightShift64(int64_t value, int32_t spaces) { + return (int64_t)((uint64_t)(value) >> spaces); +} + +// Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) { + return (int32_t)(GPBLogicalRightShift32((int32_t)n, 1) ^ -((int32_t)(n) & 1)); +} + +// Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) { + return (int64_t)(GPBLogicalRightShift64((int64_t)n, 1) ^ -((int64_t)(n) & 1)); +} + +// Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) { + // Note: the right-shift must be arithmetic + return ((uint32_t)n << 1) ^ (uint32_t)(n >> 31); +} + +// Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) { + // Note: the right-shift must be arithmetic + return ((uint64_t)n << 1) ^ (uint64_t)(n >> 63); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +GPB_INLINE BOOL GPBDataTypeIsObject(GPBDataType type) { + switch (type) { + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return YES; + default: + return NO; + } +} + +GPB_INLINE BOOL GPBDataTypeIsMessage(GPBDataType type) { + switch (type) { + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return YES; + default: + return NO; + } +} + +GPB_INLINE BOOL GPBFieldDataTypeIsMessage(GPBFieldDescriptor *field) { + return GPBDataTypeIsMessage(field->description_->dataType); +} + +GPB_INLINE BOOL GPBFieldDataTypeIsObject(GPBFieldDescriptor *field) { + return GPBDataTypeIsObject(field->description_->dataType); +} + +GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) { + return GPBDataTypeIsMessage(ext->description_->dataType); +} + +// The field is an array/map or it has an object value. +GPB_INLINE BOOL GPBFieldStoresObject(GPBFieldDescriptor *field) { + GPBMessageFieldDescription *desc = field->description_; + if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) { + return YES; + } + return GPBDataTypeIsObject(desc->dataType); +} + +BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber); +void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, + BOOL value); +uint32_t GPBGetHasOneof(GPBMessage *self, int32_t index); + +GPB_INLINE BOOL +GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) { + GPBMessageFieldDescription *fieldDesc = field->description_; + return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number); +} +GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field, + BOOL value) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value); +} + +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); + +#pragma clang diagnostic pop + +//%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE) +//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value, +//% NAME$S GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL) +// This block of code is generated, do not edit it directly. + +void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float) +// This block of code is generated, do not edit it directly. + +void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + float value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double) +// This block of code is generated, do not edit it directly. + +void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + double value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t) +// This block of code is generated, do not edit it directly. + +void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND-END (8 expansions) + +int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax); + +id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); + +void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, id value, + GPBFileSyntax syntax); +void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) + value, + GPBFileSyntax syntax); + +// GPBGetObjectIvarWithField will automatically create the field (message) if +// it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil. +id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, + GPBFieldDescriptor *field); + +void GPBSetAutocreatedRetainedObjectIvarWithField( + GPBMessage *self, GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) value); + +// Clears and releases the autocreated message ivar, if it's autocreated. If +// it's not set as autocreated, this method does nothing. +void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field); + +// Returns an Objective C encoding for |selector|. |instanceSel| should be +// YES if it's an instance selector (as opposed to a class selector). +// |selector| must be a selector from MessageSignatureProtocol. +const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel); + +// Helper for text format name encoding. +// decodeData is the data describing the sepecial decodes. +// key and inputString are the input that needs decoding. +NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, + NSString *inputString); + +// A series of selectors that are used solely to get @encoding values +// for them by the dynamic protobuf runtime code. See +// GPBMessageEncodingForSelector for details. GPBRootObject conforms to +// the protocol so that it is encoded in the Objective C runtime. +@protocol GPBMessageSignatureProtocol +@optional + +#define GPB_MESSAGE_SIGNATURE_ENTRY(TYPE, NAME) \ + -(TYPE)get##NAME; \ + -(void)set##NAME : (TYPE)value; \ + -(TYPE)get##NAME##AtIndex : (NSUInteger)index; + +GPB_MESSAGE_SIGNATURE_ENTRY(BOOL, Bool) +GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, Fixed32) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SFixed32) +GPB_MESSAGE_SIGNATURE_ENTRY(float, Float) +GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, Fixed64) +GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SFixed64) +GPB_MESSAGE_SIGNATURE_ENTRY(double, Double) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Int32) +GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, Int64) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SInt32) +GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SInt64) +GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, UInt32) +GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, UInt64) +GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Bytes) +GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String) +GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message) +GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Enum) + +#undef GPB_MESSAGE_SIGNATURE_ENTRY + +- (id)getArray; +- (NSUInteger)getArrayCount; +- (void)setArray:(NSArray *)array; ++ (id)getClassValue; +@end + +BOOL GPBClassHasSel(Class aClass, SEL sel); + +CF_EXTERN_C_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.h new file mode 100644 index 0000000..04df417 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.h @@ -0,0 +1,245 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "google/protobuf/Any.pbobjc.h" + #import "google/protobuf/Duration.pbobjc.h" + #import "google/protobuf/Timestamp.pbobjc.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Errors + +/** NSError domain used for errors. */ +extern NSString *const GPBWellKnownTypesErrorDomain; + +/** Error code for NSError with GPBWellKnownTypesErrorDomain. */ +typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) { + /** The type_url could not be computed for the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeFailedToComputeTypeURL = -100, + /** type_url in a Any doesn’t match that of the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeTypeURLMismatch = -101, +}; + +#pragma mark - GPBTimestamp + +/** + * Category for GPBTimestamp to work with standard Foundation time/date types. + **/ +@interface GPBTimestamp (GBPWellKnownTypes) + +/** The NSDate representation of this GPBTimestamp. */ +@property(nonatomic, readwrite, strong) NSDate *date; + +/** + * The NSTimeInterval representation of this GPBTimestamp. + * + * @note: Not all second/nanos combinations can be represented in a + * NSTimeInterval, so getting this could be a lossy transform. + **/ +@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970; + +/** + * Initializes a GPBTimestamp with the given NSDate. + * + * @param date The date to configure the GPBTimestamp with. + * + * @return A newly initialized GPBTimestamp. + **/ +- (instancetype)initWithDate:(NSDate *)date; + +/** + * Initializes a GPBTimestamp with the given NSTimeInterval. + * + * @param timeIntervalSince1970 Time interval to configure the GPBTimestamp with. + * + * @return A newly initialized GPBTimestamp. + **/ +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970; + +@end + +#pragma mark - GPBDuration + +/** + * Category for GPBDuration to work with standard Foundation time type. + **/ +@interface GPBDuration (GBPWellKnownTypes) + +/** + * The NSTimeInterval representation of this GPBDuration. + * + * @note: Not all second/nanos combinations can be represented in a + * NSTimeInterval, so getting this could be a lossy transform. + **/ +@property(nonatomic, readwrite) NSTimeInterval timeInterval; + +/** + * Initializes a GPBDuration with the given NSTimeInterval. + * + * @param timeInterval Time interval to configure the GPBDuration with. + * + * @return A newly initialized GPBDuration. + **/ +- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval; + +// These next two methods are deprecated because GBPDuration has no need of a +// "base" time. The older methods were about symmetry with GBPTimestamp, but +// the unix epoch usage is too confusing. + +/** Deprecated, use timeInterval instead. */ +@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970 + __attribute__((deprecated("Use timeInterval"))); +/** Deprecated, use initWithTimeInterval: instead. */ +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 + __attribute__((deprecated("Use initWithTimeInterval:"))); + +@end + +#pragma mark - GPBAny + +/** + * Category for GPBAny to help work with the message within the object. + **/ +@interface GPBAny (GBPWellKnownTypes) + +/** + * Convenience method to create a GPBAny containing the serialized message. + * This uses type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Convenience method to create a GPBAny containing the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Unpacks the serialized message as if it was an instance of the given class. + * + * @note When checking type_url, the base URL is not checked, only the fully + * qualified name. + * + * @param messageClass The class to use to deserialize the contained message. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return An instance of the given class populated with the contained data, or + * nil on failure. + */ +- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.m new file mode 100644 index 0000000..2808afe --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.m @@ -0,0 +1,272 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Importing sources here to force the linker to include our category methods in +// the static library. If these were compiled separately, the category methods +// below would be stripped by the linker. + +#import "GPBWellKnownTypes.h" + +#import "GPBUtilities_PackagePrivate.h" + +NSString *const GPBWellKnownTypesErrorDomain = + GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain); + +static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/"; + +static NSTimeInterval TimeIntervalFromSecondsAndNanos(int64_t seconds, + int32_t nanos) { + return seconds + (NSTimeInterval)nanos / 1e9; +} + +static int32_t SecondsAndNanosFromTimeInterval(NSTimeInterval time, + int64_t *outSeconds, + BOOL nanosMustBePositive) { + NSTimeInterval seconds; + NSTimeInterval nanos = modf(time, &seconds); + + if (nanosMustBePositive && (nanos < 0)) { + // Per Timestamp.proto, nanos is non-negative and "Negative second values with + // fractions must still have non-negative nanos values that count forward in + // time. Must be from 0 to 999,999,999 inclusive." + --seconds; + nanos = 1.0 + nanos; + } + + nanos *= 1e9; + *outSeconds = (int64_t)seconds; + return (int32_t)nanos; +} + +static NSString *BuildTypeURL(NSString *typeURLPrefix, NSString *fullName) { + if (typeURLPrefix.length == 0) { + return fullName; + } + + if ([typeURLPrefix hasSuffix:@"/"]) { + return [typeURLPrefix stringByAppendingString:fullName]; + } + + return [NSString stringWithFormat:@"%@/%@", typeURLPrefix, fullName]; +} + +static NSString *ParseTypeFromURL(NSString *typeURLString) { + NSRange range = [typeURLString rangeOfString:@"/" options:NSBackwardsSearch]; + if ((range.location == NSNotFound) || + (NSMaxRange(range) == typeURLString.length)) { + return nil; + } + NSString *result = [typeURLString substringFromIndex:range.location + 1]; + return result; +} + +#pragma mark - GPBTimestamp + +@implementation GPBTimestamp (GBPWellKnownTypes) + +- (instancetype)initWithDate:(NSDate *)date { + return [self initWithTimeIntervalSince1970:date.timeIntervalSince1970]; +} + +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + if ((self = [super init])) { + int64_t seconds; + int32_t nanos = SecondsAndNanosFromTimeInterval( + timeIntervalSince1970, &seconds, YES); + self.seconds = seconds; + self.nanos = nanos; + } + return self; +} + +- (NSDate *)date { + return [NSDate dateWithTimeIntervalSince1970:self.timeIntervalSince1970]; +} + +- (void)setDate:(NSDate *)date { + self.timeIntervalSince1970 = date.timeIntervalSince1970; +} + +- (NSTimeInterval)timeIntervalSince1970 { + return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); +} + +- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + int64_t seconds; + int32_t nanos = + SecondsAndNanosFromTimeInterval(timeIntervalSince1970, &seconds, YES); + self.seconds = seconds; + self.nanos = nanos; +} + +@end + +#pragma mark - GPBDuration + +@implementation GPBDuration (GBPWellKnownTypes) + +- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval { + if ((self = [super init])) { + int64_t seconds; + int32_t nanos = SecondsAndNanosFromTimeInterval( + timeInterval, &seconds, NO); + self.seconds = seconds; + self.nanos = nanos; + } + return self; +} + +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + return [self initWithTimeInterval:timeIntervalSince1970]; +} + +- (NSTimeInterval)timeInterval { + return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); +} + +- (void)setTimeInterval:(NSTimeInterval)timeInterval { + int64_t seconds; + int32_t nanos = + SecondsAndNanosFromTimeInterval(timeInterval, &seconds, NO); + self.seconds = seconds; + self.nanos = nanos; +} + +- (NSTimeInterval)timeIntervalSince1970 { + return self.timeInterval; +} + +- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + self.timeInterval = timeIntervalSince1970; +} + +@end + +#pragma mark - GPBAny + +@implementation GPBAny (GBPWellKnownTypes) + ++ (instancetype)anyWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self anyWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + ++ (instancetype)anyWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + return [[[self alloc] initWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr] autorelease]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self initWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + self = [self init]; + if (self) { + if (![self packWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr]) { + [self release]; + self = nil; + } + } + return self; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self packWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + NSString *fullName = [message descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return NO; + } + if (errorPtr) { + *errorPtr = nil; + } + self.typeURL = BuildTypeURL(typeURLPrefix, fullName); + self.value = message.data; + return YES; +} + +- (GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr { + NSString *fullName = [messageClass descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return nil; + } + + NSString *expectedFullName = ParseTypeFromURL(self.typeURL); + if ((expectedFullName == nil) || ![expectedFullName isEqual:fullName]) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeTypeURLMismatch + userInfo:nil]; + } + return nil; + } + + // Any is proto3, which means no extensions, so this assumes anything put + // within an any also won't need extensions. A second helper could be added + // if needed. + return [messageClass parseFromData:self.value + error:errorPtr]; +} + +@end diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWireFormat.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWireFormat.h new file mode 100644 index 0000000..c5941a3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWireFormat.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBRuntimeTypes.h" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +typedef enum { + GPBWireFormatVarint = 0, + GPBWireFormatFixed64 = 1, + GPBWireFormatLengthDelimited = 2, + GPBWireFormatStartGroup = 3, + GPBWireFormatEndGroup = 4, + GPBWireFormatFixed32 = 5, +} GPBWireFormat; + +enum { + GPBWireFormatMessageSetItem = 1, + GPBWireFormatMessageSetTypeId = 2, + GPBWireFormatMessageSetMessage = 3 +}; + +uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) + __attribute__((const)); +GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const)); +uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const)); +BOOL GPBWireFormatIsValidTag(uint32_t tag) __attribute__((const)); + +GPBWireFormat GPBWireFormatForType(GPBDataType dataType, BOOL isPacked) + __attribute__((const)); + +#define GPBWireFormatMessageSetItemTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatStartGroup)) +#define GPBWireFormatMessageSetItemEndTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatEndGroup)) +#define GPBWireFormatMessageSetTypeIdTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetTypeId, GPBWireFormatVarint)) +#define GPBWireFormatMessageSetMessageTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetMessage, \ + GPBWireFormatLengthDelimited)) + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWireFormat.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWireFormat.m new file mode 100644 index 0000000..860a339 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/GPBWireFormat.m @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBWireFormat.h" + +#import "GPBUtilities_PackagePrivate.h" + +enum { + GPBWireFormatTagTypeBits = 3, + GPBWireFormatTagTypeMask = 7 /* = (1 << GPBWireFormatTagTypeBits) - 1 */, +}; + +uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) { + return (fieldNumber << GPBWireFormatTagTypeBits) | wireType; +} + +GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) { + return (GPBWireFormat)(tag & GPBWireFormatTagTypeMask); +} + +uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) { + return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits); +} + +BOOL GPBWireFormatIsValidTag(uint32_t tag) { + uint32_t formatBits = (tag & GPBWireFormatTagTypeMask); + // The valid GPBWireFormat* values are 0-5, anything else is not a valid tag. + BOOL result = (formatBits <= 5); + return result; +} + +GPBWireFormat GPBWireFormatForType(GPBDataType type, BOOL isPacked) { + if (isPacked) { + return GPBWireFormatLengthDelimited; + } + + static const GPBWireFormat format[GPBDataType_Count] = { + GPBWireFormatVarint, // GPBDataTypeBool + GPBWireFormatFixed32, // GPBDataTypeFixed32 + GPBWireFormatFixed32, // GPBDataTypeSFixed32 + GPBWireFormatFixed32, // GPBDataTypeFloat + GPBWireFormatFixed64, // GPBDataTypeFixed64 + GPBWireFormatFixed64, // GPBDataTypeSFixed64 + GPBWireFormatFixed64, // GPBDataTypeDouble + GPBWireFormatVarint, // GPBDataTypeInt32 + GPBWireFormatVarint, // GPBDataTypeInt64 + GPBWireFormatVarint, // GPBDataTypeSInt32 + GPBWireFormatVarint, // GPBDataTypeSInt64 + GPBWireFormatVarint, // GPBDataTypeUInt32 + GPBWireFormatVarint, // GPBDataTypeUInt64 + GPBWireFormatLengthDelimited, // GPBDataTypeBytes + GPBWireFormatLengthDelimited, // GPBDataTypeString + GPBWireFormatLengthDelimited, // GPBDataTypeMessage + GPBWireFormatStartGroup, // GPBDataTypeGroup + GPBWireFormatVarint // GPBDataTypeEnum + }; + return format[type]; +} diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.h new file mode 100644 index 0000000..2091d72 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.h @@ -0,0 +1,183 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBAnyRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBAnyRoot : GPBRootObject +@end + +#pragma mark - GPBAny + +typedef GPB_ENUM(GPBAny_FieldNumber) { + GPBAny_FieldNumber_TypeURL = 1, + GPBAny_FieldNumber_Value = 2, +}; + +/** + * `Any` contains an arbitrary serialized protocol buffer message along with a + * URL that describes the type of the serialized message. + * + * Protobuf library provides support to pack/unpack Any values in the form + * of utility functions or additional generated methods of the Any type. + * + * Example 1: Pack and unpack a message in C++. + * + * Foo foo = ...; + * Any any; + * any.PackFrom(foo); + * ... + * if (any.UnpackTo(&foo)) { + * ... + * } + * + * Example 2: Pack and unpack a message in Java. + * + * Foo foo = ...; + * Any any = Any.pack(foo); + * ... + * if (any.is(Foo.class)) { + * foo = any.unpack(Foo.class); + * } + * + * Example 3: Pack and unpack a message in Python. + * + * foo = Foo(...) + * any = Any() + * any.Pack(foo) + * ... + * if any.Is(Foo.DESCRIPTOR): + * any.Unpack(foo) + * ... + * + * Example 4: Pack and unpack a message in Go + * + * foo := &pb.Foo{...} + * any, err := ptypes.MarshalAny(foo) + * ... + * foo := &pb.Foo{} + * if err := ptypes.UnmarshalAny(any, foo); err != nil { + * ... + * } + * + * The pack methods provided by protobuf library will by default use + * 'type.googleapis.com/full.type.name' as the type URL and the unpack + * methods only use the fully qualified type name after the last '/' + * in the type URL, for example "foo.bar.com/x/y.z" will yield type + * name "y.z". + * + * + * JSON + * ==== + * The JSON representation of an `Any` value uses the regular + * representation of the deserialized, embedded message, with an + * additional field `\@type` which contains the type URL. Example: + * + * package google.profile; + * message Person { + * string first_name = 1; + * string last_name = 2; + * } + * + * { + * "\@type": "type.googleapis.com/google.profile.Person", + * "firstName": , + * "lastName": + * } + * + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `\@type` + * field. Example (for message [google.protobuf.Duration][]): + * + * { + * "\@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + **/ +@interface GPBAny : GPBMessage + +/** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; + +/** Must be a valid serialized protocol buffer of the above specified type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.m new file mode 100644 index 0000000..7ca84ff --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.m @@ -0,0 +1,114 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Any.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBAnyRoot + +@implementation GPBAnyRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBAnyRoot_FileDescriptor + +static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBAny + +@implementation GPBAny + +@dynamic typeURL; +@dynamic value; + +typedef struct GPBAny__storage_ { + uint32_t _has_storage_[1]; + NSString *typeURL; + NSData *value; +} GPBAny__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "typeURL", + .dataTypeSpecific.className = NULL, + .number = GPBAny_FieldNumber_TypeURL, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBAny_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBAny__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBAny class] + rootClass:[GPBAnyRoot class] + file:GPBAnyRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBAny__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\004\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.h new file mode 100644 index 0000000..c93f3f1 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.h @@ -0,0 +1,311 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBMethod; +@class GPBMixin; +@class GPBOption; +@class GPBSourceContext; +GPB_ENUM_FWD_DECLARE(GPBSyntax); + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBApiRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBApiRoot : GPBRootObject +@end + +#pragma mark - GPBApi + +typedef GPB_ENUM(GPBApi_FieldNumber) { + GPBApi_FieldNumber_Name = 1, + GPBApi_FieldNumber_MethodsArray = 2, + GPBApi_FieldNumber_OptionsArray = 3, + GPBApi_FieldNumber_Version = 4, + GPBApi_FieldNumber_SourceContext = 5, + GPBApi_FieldNumber_MixinsArray = 6, + GPBApi_FieldNumber_Syntax = 7, +}; + +/** + * Api is a light-weight descriptor for an API Interface. + * + * Interfaces are also described as "protocol buffer services" in some contexts, + * such as by the "service" keyword in a .proto file, but they are different + * from API Services, which represent a concrete implementation of an interface + * as opposed to simply a description of methods and bindings. They are also + * sometimes simply referred to as "APIs" in other contexts, such as the name of + * this message itself. See https://cloud.google.com/apis/design/glossary for + * detailed terminology. + **/ +@interface GPBApi : GPBMessage + +/** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** The methods of this interface, in unspecified order. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodsArray; +/** The number of items in @c methodsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger methodsArray_Count; + +/** Any metadata attached to the interface. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *version; + +/** + * Source context for the protocol buffer service represented by this + * message. + **/ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** Included interfaces. See [Mixin][]. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *mixinsArray; +/** The number of items in @c mixinsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger mixinsArray_Count; + +/** The source syntax of the service. */ +@property(nonatomic, readwrite) enum GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBApi's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBApi_Syntax_RawValue(GPBApi *message); +/** + * Sets the raw value of an @c GPBApi's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value); + +#pragma mark - GPBMethod + +typedef GPB_ENUM(GPBMethod_FieldNumber) { + GPBMethod_FieldNumber_Name = 1, + GPBMethod_FieldNumber_RequestTypeURL = 2, + GPBMethod_FieldNumber_RequestStreaming = 3, + GPBMethod_FieldNumber_ResponseTypeURL = 4, + GPBMethod_FieldNumber_ResponseStreaming = 5, + GPBMethod_FieldNumber_OptionsArray = 6, + GPBMethod_FieldNumber_Syntax = 7, +}; + +/** + * Method represents a method of an API interface. + **/ +@interface GPBMethod : GPBMessage + +/** The simple name of this method. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** A URL of the input message type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL; + +/** If true, the request is streamed. */ +@property(nonatomic, readwrite) BOOL requestStreaming; + +/** The URL of the output message type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL; + +/** If true, the response is streamed. */ +@property(nonatomic, readwrite) BOOL responseStreaming; + +/** Any metadata attached to the method. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source syntax of this method. */ +@property(nonatomic, readwrite) enum GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBMethod's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBMethod_Syntax_RawValue(GPBMethod *message); +/** + * Sets the raw value of an @c GPBMethod's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value); + +#pragma mark - GPBMixin + +typedef GPB_ENUM(GPBMixin_FieldNumber) { + GPBMixin_FieldNumber_Name = 1, + GPBMixin_FieldNumber_Root = 2, +}; + +/** + * Declares an API Interface to be included in this interface. The including + * interface must redeclare all the methods from the included interface, but + * documentation and options are inherited as follows: + * + * - If after comment and whitespace stripping, the documentation + * string of the redeclared method is empty, it will be inherited + * from the original method. + * + * - Each annotation belonging to the service config (http, + * visibility) which is not set in the redeclared method will be + * inherited. + * + * - If an http annotation is inherited, the path pattern will be + * modified as follows. Any version prefix will be replaced by the + * version of the including interface plus the [root][] path if + * specified. + * + * Example of a simple mixin: + * + * package google.acl.v1; + * service AccessControl { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v1/{resource=**}:getAcl"; + * } + * } + * + * package google.storage.v2; + * service Storage { + * rpc GetAcl(GetAclRequest) returns (Acl); + * + * // Get a data record. + * rpc GetData(GetDataRequest) returns (Data) { + * option (google.api.http).get = "/v2/{resource=**}"; + * } + * } + * + * Example of a mixin configuration: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * + * The mixin construct implies that all methods in `AccessControl` are + * also declared with same name and request/response types in + * `Storage`. A documentation generator or annotation processor will + * see the effective `Storage.GetAcl` method after inherting + * documentation and annotations as follows: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/{resource=**}:getAcl"; + * } + * ... + * } + * + * Note how the version in the path pattern changed from `v1` to `v2`. + * + * If the `root` field in the mixin is specified, it should be a + * relative path under which inherited HTTP paths are placed. Example: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * root: acls + * + * This implies the following inherited HTTP annotation: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + * } + * ... + * } + **/ +@interface GPBMixin : GPBMessage + +/** The fully qualified name of the interface which is included. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *root; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.m new file mode 100644 index 0000000..d63a3e6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.m @@ -0,0 +1,362 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "google/protobuf/Api.pbobjc.h" + #import "google/protobuf/SourceContext.pbobjc.h" + #import "google/protobuf/Type.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBApiRoot + +@implementation GPBApiRoot + +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. + +@end + +#pragma mark - GPBApiRoot_FileDescriptor + +static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBApi + +@implementation GPBApi + +@dynamic name; +@dynamic methodsArray, methodsArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic version; +@dynamic hasSourceContext, sourceContext; +@dynamic mixinsArray, mixinsArray_Count; +@dynamic syntax; + +typedef struct GPBApi__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *methodsArray; + NSMutableArray *optionsArray; + NSString *version; + GPBSourceContext *sourceContext; + NSMutableArray *mixinsArray; +} GPBApi__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBApi_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBApi__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "methodsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod), + .number = GPBApi_FieldNumber_MethodsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBApi_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "version", + .dataTypeSpecific.className = NULL, + .number = GPBApi_FieldNumber_Version, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBApi__storage_, version), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "sourceContext", + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .number = GPBApi_FieldNumber_SourceContext, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "mixinsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBMixin), + .number = GPBApi_FieldNumber_MixinsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBApi_FieldNumber_Syntax, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBApi__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBApi class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBApi__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBApi_Syntax_RawValue(GPBApi *message) { + GPBDescriptor *descriptor = [GPBApi descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) { + GPBDescriptor *descriptor = [GPBApi descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBMethod + +@implementation GPBMethod + +@dynamic name; +@dynamic requestTypeURL; +@dynamic requestStreaming; +@dynamic responseTypeURL; +@dynamic responseStreaming; +@dynamic optionsArray, optionsArray_Count; +@dynamic syntax; + +typedef struct GPBMethod__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSString *requestTypeURL; + NSString *responseTypeURL; + NSMutableArray *optionsArray; +} GPBMethod__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBMethod__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "requestTypeURL", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_RequestTypeURL, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "requestStreaming", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_RequestStreaming, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "responseTypeURL", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_ResponseTypeURL, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "responseStreaming", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_ResponseStreaming, + .hasIndex = 5, + .offset = 6, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBMethod_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBMethod_FieldNumber_Syntax, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethod class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBMethod__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\002\002\007\244\241!!\000\004\010\244\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) { + GPBDescriptor *descriptor = [GPBMethod descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) { + GPBDescriptor *descriptor = [GPBMethod descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBMixin + +@implementation GPBMixin + +@dynamic name; +@dynamic root; + +typedef struct GPBMixin__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + NSString *root; +} GPBMixin__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBMixin_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBMixin__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "root", + .dataTypeSpecific.className = NULL, + .number = GPBMixin_FieldNumber_Root, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBMixin__storage_, root), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMixin class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBMixin__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.h new file mode 100644 index 0000000..3e36759 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.h @@ -0,0 +1,145 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBDurationRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBDurationRoot : GPBRootObject +@end + +#pragma mark - GPBDuration + +typedef GPB_ENUM(GPBDuration_FieldNumber) { + GPBDuration_FieldNumber_Seconds = 1, + GPBDuration_FieldNumber_Nanos = 2, +}; + +/** + * A Duration represents a signed, fixed-length span of time represented + * as a count of seconds and fractions of seconds at nanosecond + * resolution. It is independent of any calendar and concepts like "day" + * or "month". It is related to Timestamp in that the difference between + * two Timestamp values is a Duration and it can be added or subtracted + * from a Timestamp. Range is approximately +-10,000 years. + * + * # Examples + * + * Example 1: Compute Duration from two Timestamps in pseudo code. + * + * Timestamp start = ...; + * Timestamp end = ...; + * Duration duration = ...; + * + * duration.seconds = end.seconds - start.seconds; + * duration.nanos = end.nanos - start.nanos; + * + * if (duration.seconds < 0 && duration.nanos > 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (durations.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * + * Example 3: Compute Duration from datetime.timedelta in Python. + * + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * + * # JSON Mapping + * + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + **/ +@interface GPBDuration : GPBMessage + +/** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + **/ +@property(nonatomic, readwrite) int64_t seconds; + +/** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + **/ +@property(nonatomic, readwrite) int32_t nanos; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.m new file mode 100644 index 0000000..3fa7024 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.m @@ -0,0 +1,109 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Duration.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBDurationRoot + +@implementation GPBDurationRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBDurationRoot_FileDescriptor + +static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDuration + +@implementation GPBDuration + +@dynamic seconds; +@dynamic nanos; + +typedef struct GPBDuration__storage_ { + uint32_t _has_storage_[1]; + int32_t nanos; + int64_t seconds; +} GPBDuration__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "seconds", + .dataTypeSpecific.className = NULL, + .number = GPBDuration_FieldNumber_Seconds, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "nanos", + .dataTypeSpecific.className = NULL, + .number = GPBDuration_FieldNumber_Nanos, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDuration class] + rootClass:[GPBDurationRoot class] + file:GPBDurationRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBDuration__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.h new file mode 100644 index 0000000..fdc247a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.h @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBEmptyRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBEmptyRoot : GPBRootObject +@end + +#pragma mark - GPBEmpty + +/** + * A generic empty message that you can re-use to avoid defining duplicated + * empty messages in your APIs. A typical example is to use it as the request + * or the response type of an API method. For instance: + * + * service Foo { + * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + * } + * + * The JSON representation for `Empty` is empty JSON object `{}`. + **/ +@interface GPBEmpty : GPBMessage + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.m new file mode 100644 index 0000000..51f15f3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.m @@ -0,0 +1,85 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Empty.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBEmptyRoot + +@implementation GPBEmptyRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBEmptyRoot_FileDescriptor + +static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBEmpty + +@implementation GPBEmpty + + +typedef struct GPBEmpty__storage_ { + uint32_t _has_storage_[1]; +} GPBEmpty__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] + rootClass:[GPBEmptyRoot class] + file:GPBEmptyRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GPBEmpty__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.h new file mode 100644 index 0000000..72cac9a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -0,0 +1,273 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBFieldMaskRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBFieldMaskRoot : GPBRootObject +@end + +#pragma mark - GPBFieldMask + +typedef GPB_ENUM(GPBFieldMask_FieldNumber) { + GPBFieldMask_FieldNumber_PathsArray = 1, +}; + +/** + * `FieldMask` represents a set of symbolic field paths, for example: + * + * paths: "f.a" + * paths: "f.b.d" + * + * Here `f` represents a field in some root message, `a` and `b` + * fields in the message found in `f`, and `d` a field found in the + * message in `f.b`. + * + * Field masks are used to specify a subset of fields that should be + * returned by a get operation or modified by an update operation. + * Field masks also have a custom JSON encoding (see below). + * + * # Field Masks in Projections + * + * When used in the context of a projection, a response message or + * sub-message is filtered by the API to only contain those fields as + * specified in the mask. For example, if the mask in the previous + * example is applied to a response message as follows: + * + * f { + * a : 22 + * b { + * d : 1 + * x : 2 + * } + * y : 13 + * } + * z: 8 + * + * The result will not contain specific values for fields x,y and z + * (their value will be set to the default, and omitted in proto text + * output): + * + * + * f { + * a : 22 + * b { + * d : 1 + * } + * } + * + * A repeated field is not allowed except at the last position of a + * paths string. + * + * If a FieldMask object is not present in a get operation, the + * operation applies to all fields (as if a FieldMask of all fields + * had been specified). + * + * Note that a field mask does not necessarily apply to the + * top-level response message. In case of a REST get operation, the + * field mask applies directly to the response, but in case of a REST + * list operation, the mask instead applies to each individual message + * in the returned resource list. In case of a REST custom method, + * other definitions may be used. Where the mask applies will be + * clearly documented together with its declaration in the API. In + * any case, the effect on the returned resource/resources is required + * behavior for APIs. + * + * # Field Masks in Update Operations + * + * A field mask in update operations specifies which fields of the + * targeted resource are going to be updated. The API is required + * to only change the values of the fields as specified in the mask + * and leave the others untouched. If a resource is passed in to + * describe the updated values, the API ignores the values of all + * fields not covered by the mask. + * + * If a repeated field is specified for an update operation, new values will + * be appended to the existing repeated field in the target resource. Note that + * a repeated field is only allowed in the last position of a `paths` string. + * + * If a sub-message is specified in the last position of the field mask for an + * update operation, then new value will be merged into the existing sub-message + * in the target resource. + * + * For example, given the target message: + * + * f { + * b { + * d: 1 + * x: 2 + * } + * c: [1] + * } + * + * And an update message: + * + * f { + * b { + * d: 10 + * } + * c: [2] + * } + * + * then if the field mask is: + * + * paths: ["f.b", "f.c"] + * + * then the result will be: + * + * f { + * b { + * d: 10 + * x: 2 + * } + * c: [1, 2] + * } + * + * An implementation may provide options to override this default behavior for + * repeated and message fields. + * + * In order to reset a field's value to the default, the field must + * be in the mask and set to the default value in the provided resource. + * Hence, in order to reset all fields of a resource, provide a default + * instance of the resource and set all fields in the mask, or do + * not provide a mask as described below. + * + * If a field mask is not present on update, the operation applies to + * all fields (as if a field mask of all fields has been specified). + * Note that in the presence of schema evolution, this may mean that + * fields the client does not know and has therefore not filled into + * the request will be reset to their default. If this is unwanted + * behavior, a specific service may require a client to always specify + * a field mask, producing an error if not. + * + * As with get operations, the location of the resource which + * describes the updated values in the request message depends on the + * operation kind. In any case, the effect of the field mask is + * required to be honored by the API. + * + * ## Considerations for HTTP REST + * + * The HTTP kind of an update operation which uses a field mask must + * be set to PATCH instead of PUT in order to satisfy HTTP semantics + * (PUT must only be used for full updates). + * + * # JSON Encoding of Field Masks + * + * In JSON, a field mask is encoded as a single string where paths are + * separated by a comma. Fields name in each path are converted + * to/from lower-camel naming conventions. + * + * As an example, consider the following message declarations: + * + * message Profile { + * User user = 1; + * Photo photo = 2; + * } + * message User { + * string display_name = 1; + * string address = 2; + * } + * + * In proto a field mask for `Profile` may look as such: + * + * mask { + * paths: "user.display_name" + * paths: "photo" + * } + * + * In JSON, the same mask is represented as below: + * + * { + * mask: "user.displayName,photo" + * } + * + * # Field Masks and Oneof Fields + * + * Field masks treat fields in oneofs just as regular fields. Consider the + * following message: + * + * message SampleMessage { + * oneof test_oneof { + * string name = 4; + * SubMessage sub_message = 9; + * } + * } + * + * The field mask can be: + * + * mask { + * paths: "name" + * } + * + * Or: + * + * mask { + * paths: "sub_message" + * } + * + * Note that oneof type names ("test_oneof" in this case) cannot be used in + * paths. + * + * ## Field Mask Verification + * + * The implementation of any API method which has a FieldMask type field in the + * request should verify the included field paths, and return an + * `INVALID_ARGUMENT` error if any path is duplicated or unmappable. + **/ +@interface GPBFieldMask : GPBMessage + +/** The set of field mask paths. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *pathsArray; +/** The number of items in @c pathsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger pathsArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.m new file mode 100644 index 0000000..ff27318 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -0,0 +1,98 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/FieldMask.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBFieldMaskRoot + +@implementation GPBFieldMaskRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBFieldMaskRoot_FileDescriptor + +static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBFieldMask + +@implementation GPBFieldMask + +@dynamic pathsArray, pathsArray_Count; + +typedef struct GPBFieldMask__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *pathsArray; +} GPBFieldMask__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "pathsArray", + .dataTypeSpecific.className = NULL, + .number = GPBFieldMask_FieldNumber_PathsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] + rootClass:[GPBFieldMaskRoot class] + file:GPBFieldMaskRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBFieldMask__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.h new file mode 100644 index 0000000..e492395 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -0,0 +1,77 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBSourceContextRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBSourceContextRoot : GPBRootObject +@end + +#pragma mark - GPBSourceContext + +typedef GPB_ENUM(GPBSourceContext_FieldNumber) { + GPBSourceContext_FieldNumber_FileName = 1, +}; + +/** + * `SourceContext` represents information about the source of a + * protobuf element, like the file in which it is defined. + **/ +@interface GPBSourceContext : GPBMessage + +/** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.m new file mode 100644 index 0000000..c93871e --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -0,0 +1,98 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/SourceContext.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBSourceContextRoot + +@implementation GPBSourceContextRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBSourceContextRoot_FileDescriptor + +static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBSourceContext + +@implementation GPBSourceContext + +@dynamic fileName; + +typedef struct GPBSourceContext__storage_ { + uint32_t _has_storage_[1]; + NSString *fileName; +} GPBSourceContext__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fileName", + .dataTypeSpecific.className = NULL, + .number = GPBSourceContext_FieldNumber_FileName, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] + rootClass:[GPBSourceContextRoot class] + file:GPBSourceContextRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBSourceContext__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.h new file mode 100644 index 0000000..fb20425 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.h @@ -0,0 +1,204 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBListValue; +@class GPBStruct; +@class GPBValue; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GPBNullValue + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + **/ +typedef GPB_ENUM(GPBNullValue) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Null value. */ + GPBNullValue_NullValue = 0, +}; + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBNullValue_IsValidValue(int32_t value); + +#pragma mark - GPBStructRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBStructRoot : GPBRootObject +@end + +#pragma mark - GPBStruct + +typedef GPB_ENUM(GPBStruct_FieldNumber) { + GPBStruct_FieldNumber_Fields = 1, +}; + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + **/ +@interface GPBStruct : GPBMessage + +/** Unordered map of dynamically typed values. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary *fields; +/** The number of items in @c fields without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger fields_Count; + +@end + +#pragma mark - GPBValue + +typedef GPB_ENUM(GPBValue_FieldNumber) { + GPBValue_FieldNumber_NullValue = 1, + GPBValue_FieldNumber_NumberValue = 2, + GPBValue_FieldNumber_StringValue = 3, + GPBValue_FieldNumber_BoolValue = 4, + GPBValue_FieldNumber_StructValue = 5, + GPBValue_FieldNumber_ListValue = 6, +}; + +typedef GPB_ENUM(GPBValue_Kind_OneOfCase) { + GPBValue_Kind_OneOfCase_GPBUnsetOneOfCase = 0, + GPBValue_Kind_OneOfCase_NullValue = 1, + GPBValue_Kind_OneOfCase_NumberValue = 2, + GPBValue_Kind_OneOfCase_StringValue = 3, + GPBValue_Kind_OneOfCase_BoolValue = 4, + GPBValue_Kind_OneOfCase_StructValue = 5, + GPBValue_Kind_OneOfCase_ListValue = 6, +}; + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of that + * variants, absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + **/ +@interface GPBValue : GPBMessage + +/** The kind of value. */ +@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase; + +/** Represents a null value. */ +@property(nonatomic, readwrite) GPBNullValue nullValue; + +/** Represents a double value. */ +@property(nonatomic, readwrite) double numberValue; + +/** Represents a string value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue; + +/** Represents a boolean value. */ +@property(nonatomic, readwrite) BOOL boolValue; + +/** Represents a structured value. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue; + +/** Represents a repeated `Value`. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue; + +@end + +/** + * Fetches the raw value of a @c GPBValue's @c nullValue property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBValue_NullValue_RawValue(GPBValue *message); +/** + * Sets the raw value of an @c GPBValue's @c nullValue property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value); + +/** + * Clears whatever value was set for the oneof 'kind'. + **/ +void GPBValue_ClearKindOneOfCase(GPBValue *message); + +#pragma mark - GPBListValue + +typedef GPB_ENUM(GPBListValue_FieldNumber) { + GPBListValue_FieldNumber_ValuesArray = 1, +}; + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + **/ +@interface GPBListValue : GPBMessage + +/** Repeated field of dynamically typed values. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valuesArray; +/** The number of items in @c valuesArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger valuesArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.m new file mode 100644 index 0000000..169a275 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.m @@ -0,0 +1,302 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#import + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Struct.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +#pragma mark - GPBStructRoot + +@implementation GPBStructRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBStructRoot_FileDescriptor + +static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBNullValue + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "NullValue\000"; + static const int32_t values[] = { + GPBNullValue_NullValue, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBNullValue) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBNullValue_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBNullValue_IsValidValue(int32_t value__) { + switch (value__) { + case GPBNullValue_NullValue: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBStruct + +@implementation GPBStruct + +@dynamic fields, fields_Count; + +typedef struct GPBStruct__storage_ { + uint32_t _has_storage_[1]; + NSMutableDictionary *fields; +} GPBStruct__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fields", + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), + .number = GPBStruct_FieldNumber_Fields, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBStruct__storage_, fields), + .flags = GPBFieldMapKeyString, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStruct class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBStruct__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBValue + +@implementation GPBValue + +@dynamic kindOneOfCase; +@dynamic nullValue; +@dynamic numberValue; +@dynamic stringValue; +@dynamic boolValue; +@dynamic structValue; +@dynamic listValue; + +typedef struct GPBValue__storage_ { + uint32_t _has_storage_[2]; + GPBNullValue nullValue; + NSString *stringValue; + GPBStruct *structValue; + GPBListValue *listValue; + double numberValue; +} GPBValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "nullValue", + .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, + .number = GPBValue_FieldNumber_NullValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, nullValue), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "numberValue", + .dataTypeSpecific.className = NULL, + .number = GPBValue_FieldNumber_NumberValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, numberValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeDouble, + }, + { + .name = "stringValue", + .dataTypeSpecific.className = NULL, + .number = GPBValue_FieldNumber_StringValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, stringValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "boolValue", + .dataTypeSpecific.className = NULL, + .number = GPBValue_FieldNumber_BoolValue, + .hasIndex = -1, + .offset = 0, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "structValue", + .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct), + .number = GPBValue_FieldNumber_StructValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, structValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "listValue", + .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue), + .number = GPBValue_FieldNumber_ListValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, listValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + static const char *oneofs[] = { + "kind", + }; + [localDescriptor setupOneofs:oneofs + count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) + firstHasIndex:-1]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBValue_NullValue_RawValue(GPBValue *message) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +void GPBValue_ClearKindOneOfCase(GPBValue *message) { + GPBDescriptor *descriptor = [message descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBMaybeClearOneof(message, oneof, -1, 0); +} +#pragma mark - GPBListValue + +@implementation GPBListValue + +@dynamic valuesArray, valuesArray_Count; + +typedef struct GPBListValue__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *valuesArray; +} GPBListValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "valuesArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), + .number = GPBListValue_FieldNumber_ValuesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBListValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBListValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.h new file mode 100644 index 0000000..f6ea25c --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -0,0 +1,165 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBTimestampRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBTimestampRoot : GPBRootObject +@end + +#pragma mark - GPBTimestamp + +typedef GPB_ENUM(GPBTimestamp_FieldNumber) { + GPBTimestamp_FieldNumber_Seconds = 1, + GPBTimestamp_FieldNumber_Nanos = 2, +}; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * + * Example 5: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) + * with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one + * can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + **/ +@interface GPBTimestamp : GPBMessage + +/** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + **/ +@property(nonatomic, readwrite) int64_t seconds; + +/** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + **/ +@property(nonatomic, readwrite) int32_t nanos; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.m new file mode 100644 index 0000000..b6393e3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -0,0 +1,109 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Timestamp.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBTimestampRoot + +@implementation GPBTimestampRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBTimestampRoot_FileDescriptor + +static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBTimestamp + +@implementation GPBTimestamp + +@dynamic seconds; +@dynamic nanos; + +typedef struct GPBTimestamp__storage_ { + uint32_t _has_storage_[1]; + int32_t nanos; + int64_t seconds; +} GPBTimestamp__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "seconds", + .dataTypeSpecific.className = NULL, + .number = GPBTimestamp_FieldNumber_Seconds, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "nanos", + .dataTypeSpecific.className = NULL, + .number = GPBTimestamp_FieldNumber_Nanos, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class] + rootClass:[GPBTimestampRoot class] + file:GPBTimestampRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBTimestamp__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.h new file mode 100644 index 0000000..e14d15d --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.h @@ -0,0 +1,444 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBAny; +@class GPBEnumValue; +@class GPBField; +@class GPBOption; +@class GPBSourceContext; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GPBSyntax + +/** The syntax in which a protocol buffer element is defined. */ +typedef GPB_ENUM(GPBSyntax) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Syntax `proto2`. */ + GPBSyntax_SyntaxProto2 = 0, + + /** Syntax `proto3`. */ + GPBSyntax_SyntaxProto3 = 1, +}; + +GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBSyntax_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Kind + +/** Basic field types. */ +typedef GPB_ENUM(GPBField_Kind) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Field type unknown. */ + GPBField_Kind_TypeUnknown = 0, + + /** Field type double. */ + GPBField_Kind_TypeDouble = 1, + + /** Field type float. */ + GPBField_Kind_TypeFloat = 2, + + /** Field type int64. */ + GPBField_Kind_TypeInt64 = 3, + + /** Field type uint64. */ + GPBField_Kind_TypeUint64 = 4, + + /** Field type int32. */ + GPBField_Kind_TypeInt32 = 5, + + /** Field type fixed64. */ + GPBField_Kind_TypeFixed64 = 6, + + /** Field type fixed32. */ + GPBField_Kind_TypeFixed32 = 7, + + /** Field type bool. */ + GPBField_Kind_TypeBool = 8, + + /** Field type string. */ + GPBField_Kind_TypeString = 9, + + /** Field type group. Proto2 syntax only, and deprecated. */ + GPBField_Kind_TypeGroup = 10, + + /** Field type message. */ + GPBField_Kind_TypeMessage = 11, + + /** Field type bytes. */ + GPBField_Kind_TypeBytes = 12, + + /** Field type uint32. */ + GPBField_Kind_TypeUint32 = 13, + + /** Field type enum. */ + GPBField_Kind_TypeEnum = 14, + + /** Field type sfixed32. */ + GPBField_Kind_TypeSfixed32 = 15, + + /** Field type sfixed64. */ + GPBField_Kind_TypeSfixed64 = 16, + + /** Field type sint32. */ + GPBField_Kind_TypeSint32 = 17, + + /** Field type sint64. */ + GPBField_Kind_TypeSint64 = 18, +}; + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBField_Kind_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Cardinality + +/** Whether a field is optional, required, or repeated. */ +typedef GPB_ENUM(GPBField_Cardinality) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** For fields with unknown cardinality. */ + GPBField_Cardinality_CardinalityUnknown = 0, + + /** For optional fields. */ + GPBField_Cardinality_CardinalityOptional = 1, + + /** For required fields. Proto2 syntax only. */ + GPBField_Cardinality_CardinalityRequired = 2, + + /** For repeated fields. */ + GPBField_Cardinality_CardinalityRepeated = 3, +}; + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBField_Cardinality_IsValidValue(int32_t value); + +#pragma mark - GPBTypeRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBTypeRoot : GPBRootObject +@end + +#pragma mark - GPBType + +typedef GPB_ENUM(GPBType_FieldNumber) { + GPBType_FieldNumber_Name = 1, + GPBType_FieldNumber_FieldsArray = 2, + GPBType_FieldNumber_OneofsArray = 3, + GPBType_FieldNumber_OptionsArray = 4, + GPBType_FieldNumber_SourceContext = 5, + GPBType_FieldNumber_Syntax = 6, +}; + +/** + * A protocol buffer message type. + **/ +@interface GPBType : GPBMessage + +/** The fully qualified message name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** The list of fields. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldsArray; +/** The number of items in @c fieldsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger fieldsArray_Count; + +/** The list of types appearing in `oneof` definitions in this type. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray; +/** The number of items in @c oneofsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger oneofsArray_Count; + +/** The protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source context. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** The source syntax. */ +@property(nonatomic, readwrite) GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBType's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBType_Syntax_RawValue(GPBType *message); +/** + * Sets the raw value of an @c GPBType's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value); + +#pragma mark - GPBField + +typedef GPB_ENUM(GPBField_FieldNumber) { + GPBField_FieldNumber_Kind = 1, + GPBField_FieldNumber_Cardinality = 2, + GPBField_FieldNumber_Number = 3, + GPBField_FieldNumber_Name = 4, + GPBField_FieldNumber_TypeURL = 6, + GPBField_FieldNumber_OneofIndex = 7, + GPBField_FieldNumber_Packed = 8, + GPBField_FieldNumber_OptionsArray = 9, + GPBField_FieldNumber_JsonName = 10, + GPBField_FieldNumber_DefaultValue = 11, +}; + +/** + * A single field of a message type. + **/ +@interface GPBField : GPBMessage + +/** The field type. */ +@property(nonatomic, readwrite) GPBField_Kind kind; + +/** The field cardinality. */ +@property(nonatomic, readwrite) GPBField_Cardinality cardinality; + +/** The field number. */ +@property(nonatomic, readwrite) int32_t number; + +/** The field name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; + +/** + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + **/ +@property(nonatomic, readwrite) int32_t oneofIndex; + +/** Whether to use alternative packed wire representation. */ +@property(nonatomic, readwrite) BOOL packed; + +/** The protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The field JSON name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName; + +/** The string value of the default value of this field. Proto2 syntax only. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *defaultValue; + +@end + +/** + * Fetches the raw value of a @c GPBField's @c kind property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBField_Kind_RawValue(GPBField *message); +/** + * Sets the raw value of an @c GPBField's @c kind property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value); + +/** + * Fetches the raw value of a @c GPBField's @c cardinality property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBField_Cardinality_RawValue(GPBField *message); +/** + * Sets the raw value of an @c GPBField's @c cardinality property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value); + +#pragma mark - GPBEnum + +typedef GPB_ENUM(GPBEnum_FieldNumber) { + GPBEnum_FieldNumber_Name = 1, + GPBEnum_FieldNumber_EnumvalueArray = 2, + GPBEnum_FieldNumber_OptionsArray = 3, + GPBEnum_FieldNumber_SourceContext = 4, + GPBEnum_FieldNumber_Syntax = 5, +}; + +/** + * Enum type definition. + **/ +@interface GPBEnum : GPBMessage + +/** Enum type name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** Enum value definitions. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumvalueArray; +/** The number of items in @c enumvalueArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger enumvalueArray_Count; + +/** Protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source context. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** The source syntax. */ +@property(nonatomic, readwrite) GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBEnum's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBEnum_Syntax_RawValue(GPBEnum *message); +/** + * Sets the raw value of an @c GPBEnum's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value); + +#pragma mark - GPBEnumValue + +typedef GPB_ENUM(GPBEnumValue_FieldNumber) { + GPBEnumValue_FieldNumber_Name = 1, + GPBEnumValue_FieldNumber_Number = 2, + GPBEnumValue_FieldNumber_OptionsArray = 3, +}; + +/** + * Enum value definition. + **/ +@interface GPBEnumValue : GPBMessage + +/** Enum value name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** Enum value number. */ +@property(nonatomic, readwrite) int32_t number; + +/** Protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +@end + +#pragma mark - GPBOption + +typedef GPB_ENUM(GPBOption_FieldNumber) { + GPBOption_FieldNumber_Name = 1, + GPBOption_FieldNumber_Value = 2, +}; + +/** + * A protocol buffer option, which can be attached to a message, field, + * enumeration, etc. + **/ +@interface GPBOption : GPBMessage + +/** + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + **/ +@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.m new file mode 100644 index 0000000..6b88a4b --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.m @@ -0,0 +1,716 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#import + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "google/protobuf/Type.pbobjc.h" + #import "google/protobuf/Any.pbobjc.h" + #import "google/protobuf/SourceContext.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBTypeRoot + +@implementation GPBTypeRoot + +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. + +@end + +#pragma mark - GPBTypeRoot_FileDescriptor + +static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBSyntax + +GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "SyntaxProto2\000SyntaxProto3\000"; + static const int32_t values[] = { + GPBSyntax_SyntaxProto2, + GPBSyntax_SyntaxProto3, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBSyntax_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBSyntax_IsValidValue(int32_t value__) { + switch (value__) { + case GPBSyntax_SyntaxProto2: + case GPBSyntax_SyntaxProto3: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBType + +@implementation GPBType + +@dynamic name; +@dynamic fieldsArray, fieldsArray_Count; +@dynamic oneofsArray, oneofsArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic hasSourceContext, sourceContext; +@dynamic syntax; + +typedef struct GPBType__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *fieldsArray; + NSMutableArray *oneofsArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBType__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBType_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBType__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "fieldsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBField), + .number = GPBType_FieldNumber_FieldsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, fieldsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "oneofsArray", + .dataTypeSpecific.className = NULL, + .number = GPBType_FieldNumber_OneofsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, oneofsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBType_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "sourceContext", + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .number = GPBType_FieldNumber_SourceContext, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBType__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBType_FieldNumber_Syntax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBType__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBType class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBType__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBType_Syntax_RawValue(GPBType *message) { + GPBDescriptor *descriptor = [GPBType descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) { + GPBDescriptor *descriptor = [GPBType descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBField + +@implementation GPBField + +@dynamic kind; +@dynamic cardinality; +@dynamic number; +@dynamic name; +@dynamic typeURL; +@dynamic oneofIndex; +@dynamic packed; +@dynamic optionsArray, optionsArray_Count; +@dynamic jsonName; +@dynamic defaultValue; + +typedef struct GPBField__storage_ { + uint32_t _has_storage_[1]; + GPBField_Kind kind; + GPBField_Cardinality cardinality; + int32_t number; + int32_t oneofIndex; + NSString *name; + NSString *typeURL; + NSMutableArray *optionsArray; + NSString *jsonName; + NSString *defaultValue; +} GPBField__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "kind", + .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, + .number = GPBField_FieldNumber_Kind, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBField__storage_, kind), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "cardinality", + .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, + .number = GPBField_FieldNumber_Cardinality, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBField__storage_, cardinality), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "number", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_Number, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBField__storage_, number), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_Name, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBField__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "typeURL", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_TypeURL, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "oneofIndex", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_OneofIndex, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "packed", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_Packed, + .hasIndex = 6, + .offset = 7, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBField_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBField__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "jsonName", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_JsonName, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GPBField__storage_, jsonName), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "defaultValue", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_DefaultValue, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBField class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBField__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\006\004\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBField_Kind_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +int32_t GPBField_Cardinality_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - Enum GPBField_Kind + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt" + "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type" + "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty" + "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000" + "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ" + "eSint64\000"; + static const int32_t values[] = { + GPBField_Kind_TypeUnknown, + GPBField_Kind_TypeDouble, + GPBField_Kind_TypeFloat, + GPBField_Kind_TypeInt64, + GPBField_Kind_TypeUint64, + GPBField_Kind_TypeInt32, + GPBField_Kind_TypeFixed64, + GPBField_Kind_TypeFixed32, + GPBField_Kind_TypeBool, + GPBField_Kind_TypeString, + GPBField_Kind_TypeGroup, + GPBField_Kind_TypeMessage, + GPBField_Kind_TypeBytes, + GPBField_Kind_TypeUint32, + GPBField_Kind_TypeEnum, + GPBField_Kind_TypeSfixed32, + GPBField_Kind_TypeSfixed64, + GPBField_Kind_TypeSint32, + GPBField_Kind_TypeSint64, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Kind_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Kind_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Kind_TypeUnknown: + case GPBField_Kind_TypeDouble: + case GPBField_Kind_TypeFloat: + case GPBField_Kind_TypeInt64: + case GPBField_Kind_TypeUint64: + case GPBField_Kind_TypeInt32: + case GPBField_Kind_TypeFixed64: + case GPBField_Kind_TypeFixed32: + case GPBField_Kind_TypeBool: + case GPBField_Kind_TypeString: + case GPBField_Kind_TypeGroup: + case GPBField_Kind_TypeMessage: + case GPBField_Kind_TypeBytes: + case GPBField_Kind_TypeUint32: + case GPBField_Kind_TypeEnum: + case GPBField_Kind_TypeSfixed32: + case GPBField_Kind_TypeSfixed64: + case GPBField_Kind_TypeSint32: + case GPBField_Kind_TypeSint64: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GPBField_Cardinality + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "CardinalityUnknown\000CardinalityOptional\000C" + "ardinalityRequired\000CardinalityRepeated\000"; + static const int32_t values[] = { + GPBField_Cardinality_CardinalityUnknown, + GPBField_Cardinality_CardinalityOptional, + GPBField_Cardinality_CardinalityRequired, + GPBField_Cardinality_CardinalityRepeated, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Cardinality_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Cardinality_CardinalityUnknown: + case GPBField_Cardinality_CardinalityOptional: + case GPBField_Cardinality_CardinalityRequired: + case GPBField_Cardinality_CardinalityRepeated: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBEnum + +@implementation GPBEnum + +@dynamic name; +@dynamic enumvalueArray, enumvalueArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic hasSourceContext, sourceContext; +@dynamic syntax; + +typedef struct GPBEnum__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *enumvalueArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBEnum__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBEnum_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBEnum__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "enumvalueArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue), + .number = GPBEnum_FieldNumber_EnumvalueArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnum__storage_, enumvalueArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBEnum_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnum__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "sourceContext", + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .number = GPBEnum_FieldNumber_SourceContext, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBEnum__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBEnum_FieldNumber_Syntax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnum class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBEnum__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) { + GPBDescriptor *descriptor = [GPBEnum descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) { + GPBDescriptor *descriptor = [GPBEnum descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBEnumValue + +@implementation GPBEnumValue + +@dynamic name; +@dynamic number; +@dynamic optionsArray, optionsArray_Count; + +typedef struct GPBEnumValue__storage_ { + uint32_t _has_storage_[1]; + int32_t number; + NSString *name; + NSMutableArray *optionsArray; +} GPBEnumValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBEnumValue_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "number", + .dataTypeSpecific.className = NULL, + .number = GPBEnumValue_FieldNumber_Number, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBEnumValue_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBEnumValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBOption + +@implementation GPBOption + +@dynamic name; +@dynamic hasValue, value; + +typedef struct GPBOption__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + GPBAny *value; +} GPBOption__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBOption_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBOption__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = GPBStringifySymbol(GPBAny), + .number = GPBOption_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBOption__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBOption class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBOption__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.h b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.h new file mode 100644 index 0000000..0411e1e --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -0,0 +1,219 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBWrappersRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBWrappersRoot : GPBRootObject +@end + +#pragma mark - GPBDoubleValue + +typedef GPB_ENUM(GPBDoubleValue_FieldNumber) { + GPBDoubleValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + **/ +@interface GPBDoubleValue : GPBMessage + +/** The double value. */ +@property(nonatomic, readwrite) double value; + +@end + +#pragma mark - GPBFloatValue + +typedef GPB_ENUM(GPBFloatValue_FieldNumber) { + GPBFloatValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + **/ +@interface GPBFloatValue : GPBMessage + +/** The float value. */ +@property(nonatomic, readwrite) float value; + +@end + +#pragma mark - GPBInt64Value + +typedef GPB_ENUM(GPBInt64Value_FieldNumber) { + GPBInt64Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + **/ +@interface GPBInt64Value : GPBMessage + +/** The int64 value. */ +@property(nonatomic, readwrite) int64_t value; + +@end + +#pragma mark - GPBUInt64Value + +typedef GPB_ENUM(GPBUInt64Value_FieldNumber) { + GPBUInt64Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + **/ +@interface GPBUInt64Value : GPBMessage + +/** The uint64 value. */ +@property(nonatomic, readwrite) uint64_t value; + +@end + +#pragma mark - GPBInt32Value + +typedef GPB_ENUM(GPBInt32Value_FieldNumber) { + GPBInt32Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + **/ +@interface GPBInt32Value : GPBMessage + +/** The int32 value. */ +@property(nonatomic, readwrite) int32_t value; + +@end + +#pragma mark - GPBUInt32Value + +typedef GPB_ENUM(GPBUInt32Value_FieldNumber) { + GPBUInt32Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + **/ +@interface GPBUInt32Value : GPBMessage + +/** The uint32 value. */ +@property(nonatomic, readwrite) uint32_t value; + +@end + +#pragma mark - GPBBoolValue + +typedef GPB_ENUM(GPBBoolValue_FieldNumber) { + GPBBoolValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + **/ +@interface GPBBoolValue : GPBMessage + +/** The bool value. */ +@property(nonatomic, readwrite) BOOL value; + +@end + +#pragma mark - GPBStringValue + +typedef GPB_ENUM(GPBStringValue_FieldNumber) { + GPBStringValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + **/ +@interface GPBStringValue : GPBMessage + +/** The string value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; + +@end + +#pragma mark - GPBBytesValue + +typedef GPB_ENUM(GPBBytesValue_FieldNumber) { + GPBBytesValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + **/ +@interface GPBBytesValue : GPBMessage + +/** The bytes value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.m b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.m new file mode 100644 index 0000000..0a163fa --- /dev/null +++ b/PRODUCTNAME/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -0,0 +1,457 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Wrappers.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBWrappersRoot + +@implementation GPBWrappersRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBWrappersRoot_FileDescriptor + +static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDoubleValue + +@implementation GPBDoubleValue + +@dynamic value; + +typedef struct GPBDoubleValue__storage_ { + uint32_t _has_storage_[1]; + double value; +} GPBDoubleValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBDoubleValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeDouble, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBDoubleValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBFloatValue + +@implementation GPBFloatValue + +@dynamic value; + +typedef struct GPBFloatValue__storage_ { + uint32_t _has_storage_[1]; + float value; +} GPBFloatValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBFloatValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeFloat, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBFloatValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt64Value + +@implementation GPBInt64Value + +@dynamic value; + +typedef struct GPBInt64Value__storage_ { + uint32_t _has_storage_[1]; + int64_t value; +} GPBInt64Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBInt64Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBInt64Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt64Value + +@implementation GPBUInt64Value + +@dynamic value; + +typedef struct GPBUInt64Value__storage_ { + uint32_t _has_storage_[1]; + uint64_t value; +} GPBUInt64Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBUInt64Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBUInt64Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt32Value + +@implementation GPBInt32Value + +@dynamic value; + +typedef struct GPBInt32Value__storage_ { + uint32_t _has_storage_[1]; + int32_t value; +} GPBInt32Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBInt32Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBInt32Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt32Value + +@implementation GPBUInt32Value + +@dynamic value; + +typedef struct GPBUInt32Value__storage_ { + uint32_t _has_storage_[1]; + uint32_t value; +} GPBUInt32Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBUInt32Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBUInt32Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBBoolValue + +@implementation GPBBoolValue + +@dynamic value; + +typedef struct GPBBoolValue__storage_ { + uint32_t _has_storage_[1]; +} GPBBoolValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBBoolValue_FieldNumber_Value, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBBoolValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBStringValue + +@implementation GPBStringValue + +@dynamic value; + +typedef struct GPBStringValue__storage_ { + uint32_t _has_storage_[1]; + NSString *value; +} GPBStringValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBStringValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBStringValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBStringValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBBytesValue + +@implementation GPBBytesValue + +@dynamic value; + +typedef struct GPBBytesValue__storage_ { + uint32_t _has_storage_[1]; + NSData *value; +} GPBBytesValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBBytesValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBBytesValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/AppCenter/AppCenter.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/AppCenter/AppCenter.xcconfig new file mode 100644 index 0000000..44e1596 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/AppCenter/AppCenter.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppCenter +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"sqlite3" -l"z" -framework "CoreTelephony" -framework "Foundation" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "SafariServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppCenter +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist new file mode 100644 index 0000000..4071661 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 2.0.1 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Firebase/Firebase.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Firebase/Firebase.xcconfig new file mode 100644 index 0000000..38a8107 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Firebase/Firebase.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -weak_framework "UserNotifications" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig new file mode 100644 index 0000000..606cc43 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseAnalyticsInterop/FirebaseAnalyticsInterop.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseAnalyticsInterop/FirebaseAnalyticsInterop.xcconfig new file mode 100644 index 0000000..feac966 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseAnalyticsInterop/FirebaseAnalyticsInterop.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalyticsInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAnalyticsInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalyticsInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist new file mode 100644 index 0000000..e92eb78 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m new file mode 100644 index 0000000..4f1eb27 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCore : NSObject +@end +@implementation PodsDummy_FirebaseCore +@end diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h new file mode 100644 index 0000000..102aecb --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FirebaseCore.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" + +FOUNDATION_EXPORT double FirebaseCoreVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreVersionString[]; + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap new file mode 100644 index 0000000..4c38b87 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCore { + umbrella header "FirebaseCore-umbrella.h" + + export * + module * { export * } +} diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig new file mode 100644 index 0000000..d1d7d8c --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.0.0 Firebase_VERSION=6.0.0 +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist new file mode 100644 index 0000000..3424ca6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m new file mode 100644 index 0000000..937a03d --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseInstanceID : NSObject +@end +@implementation PodsDummy_FirebaseInstanceID +@end diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h new file mode 100644 index 0000000..90ba5de --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseInstanceID.h" +#import "FIRInstanceID.h" + +FOUNDATION_EXPORT double FirebaseInstanceIDVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseInstanceIDVersionString[]; + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap new file mode 100644 index 0000000..ff5248f --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseInstanceID { + umbrella header "FirebaseInstanceID-umbrella.h" + + export * + module * { export * } +} diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig new file mode 100644 index 0000000..6105f17 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstanceID_LIB_VERSION=4.0.0 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstanceID +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist new file mode 100644 index 0000000..3424ca6 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-dummy.m b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-dummy.m new file mode 100644 index 0000000..ec94549 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseMessaging : NSObject +@end +@implementation PodsDummy_FirebaseMessaging +@end diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-umbrella.h b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-umbrella.h new file mode 100644 index 0000000..84a9257 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseMessaging.h" +#import "FIRMessaging.h" +#import "FIRMessagingExtensionHelper.h" + +FOUNDATION_EXPORT double FirebaseMessagingVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseMessagingVersionString[]; + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap new file mode 100644 index 0000000..4ab5827 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseMessaging { + umbrella header "FirebaseMessaging-umbrella.h" + + export * + module * { export * } +} diff --git a/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging.xcconfig new file mode 100644 index 0000000..9fd4be0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/FirebaseMessaging/FirebaseMessaging.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 FIRMessaging_LIB_VERSION=4.0.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseMessaging +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleAnalytics/GoogleAnalytics.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/GoogleAnalytics/GoogleAnalytics.xcconfig deleted file mode 100644 index b7bf8cf..0000000 --- a/PRODUCTNAME/app/Pods/Target Support Files/GoogleAnalytics/GoogleAnalytics.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAnalytics -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/GoogleAnalytics" "${PODS_ROOT}/Headers/Public" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_LDFLAGS = $(inherited) -l"GoogleAnalytics" -l"sqlite3" -l"z" -framework "CoreData" -framework "SystemConfiguration" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAnalytics -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig new file mode 100644 index 0000000..e9a8c04 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist new file mode 100644 index 0000000..e92eb78 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m new file mode 100644 index 0000000..98ac4e9 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleUtilities : NSObject +@end +@implementation PodsDummy_GoogleUtilities +@end diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h new file mode 100644 index 0000000..508e631 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GULLoggerLevel.h" +#import "GULLoggerCodes.h" +#import "GULNSData+zlib.h" + +FOUNDATION_EXPORT double GoogleUtilitiesVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleUtilitiesVersionString[]; + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap new file mode 100644 index 0000000..491dd0a --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap @@ -0,0 +1,6 @@ +framework module GoogleUtilities { + umbrella header "GoogleUtilities-umbrella.h" + + export * + module * { export * } +} diff --git a/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig new file mode 100644 index 0000000..6a52687 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown index a22a809..e7e7316 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.markdown @@ -70,9 +70,1047 @@ Fabric: Copyright 2018 Google, Inc. All Rights Reserved. Use of this software is Fabric: Copyright 2018 Google, Inc. All Rights Reserved. Use of this software is subject to the terms and conditions of the Fabric Software and Services Agreement located at https://fabric.io/terms. OSS: http://get.fabric.io/terms/opensource.txt -## GoogleAnalytics +## Firebase + +Copyright 2019 Google + +## FirebaseAnalytics + +Copyright 2019 Google + +## FirebaseAnalyticsInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCore + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstanceID + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseMessaging + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleAppMeasurement + +Copyright 2019 Google + +## GoogleUtilities + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -Copyright 2016 Google ## Instabug @@ -114,6 +1152,42 @@ SOFTWARE. +## Protobuf + +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + + ## SimulatorStatusMagic The MIT License (MIT) @@ -239,6 +1313,30 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## nanopb + +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + ## OHHTTPStubs - MIT LICENSE - @@ -250,4 +1348,32 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## AppCenter + +Visual Studio App Center SDK for Apple platforms + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Generated by CocoaPods - https://cocoapods.org diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist index 147c03a..db7495a 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-acknowledgements.plist @@ -113,11 +113,1091 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI FooterText - Copyright 2016 Google + Copyright 2019 Google License Copyright Title - GoogleAnalytics + Firebase + Type + PSGroupSpecifier + + + FooterText + Copyright 2019 Google + License + Copyright + Title + FirebaseAnalytics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseAnalyticsInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCore + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstanceID + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseMessaging + Type + PSGroupSpecifier + + + FooterText + Copyright 2019 Google + License + Copyright + Title + GoogleAppMeasurement + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleUtilities Type PSGroupSpecifier @@ -173,6 +1253,48 @@ SOFTWARE. Type PSGroupSpecifier + + FooterText + Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + + License + 3-Clause BSD License + Title + Protobuf + Type + PSGroupSpecifier + FooterText The MIT License (MIT) @@ -328,6 +1450,36 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Type PSGroupSpecifier + + FooterText + Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi> + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + License + zlib + Title + nanopb + Type + PSGroupSpecifier + FooterText - MIT LICENSE - @@ -346,6 +1498,40 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI Type PSGroupSpecifier + + FooterText + Visual Studio App Center SDK for Apple platforms + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + License + MIT + Title + AppCenter + Type + PSGroupSpecifier + FooterText Generated by CocoaPods - https://cocoapods.org diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh index 58a79a5..d2a0542 100755 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-frameworks.sh @@ -94,7 +94,7 @@ install_dsym() { binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then strip_invalid_archs "$binary" fi @@ -109,6 +109,14 @@ install_dsym() { fi } +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then @@ -156,41 +164,49 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" install_framework "${BUILT_PRODUCTS_DIR}/OHHTTPStubs/OHHTTPStubs.framework" fi if [[ "$CONFIGURATION" == "Develop" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" install_framework "${BUILT_PRODUCTS_DIR}/OHHTTPStubs/OHHTTPStubs.framework" fi if [[ "$CONFIGURATION" == "Sprint" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" install_framework "${BUILT_PRODUCTS_DIR}/OHHTTPStubs/OHHTTPStubs.framework" fi if [[ "$CONFIGURATION" == "AppStore" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" install_framework "${BUILT_PRODUCTS_DIR}/OHHTTPStubs/OHHTTPStubs.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh index fe3f9c7..1b5bde4 100755 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests-resources.sh @@ -3,10 +3,15 @@ set -e set -u set -o pipefail +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then - # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy - # resources to, so exit 0 (signalling the script phase was successful). - exit 0 + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 fi mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" @@ -91,6 +96,12 @@ EOM ;; esac } +if [[ "$CONFIGURATION" == "Develop" ]]; then + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/AppCenter/AppCenterDistributeResources.bundle" +fi +if [[ "$CONFIGURATION" == "Sprint" ]]; then + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/AppCenter/AppCenterDistributeResources.bundle" +fi mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" @@ -113,6 +124,6 @@ then if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" else - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" fi fi diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig index 58a022a..fe801bd 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.appstore.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Security" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Protobuf" -framework "Security" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig index f3b12e5..124e120 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.debug.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Security" -framework "SimulatorStatusMagic" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Protobuf" -framework "Security" -framework "SimulatorStatusMagic" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig index 58a022a..b71b05e 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.develop.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Security" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "AppCenter" -framework "AppCenterDistribute" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Protobuf" -framework "Security" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "SafariServices" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig index 58a022a..b71b05e 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME-PRODUCTNAMETests/Pods-PRODUCTNAME-PRODUCTNAMETests.sprint.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Security" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "AppCenter" -framework "AppCenterDistribute" -framework "BonMot" -framework "CFNetwork" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "OHHTTPStubs" -framework "Protobuf" -framework "Security" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "SafariServices" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.markdown b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.markdown index 510ff7a..7f46657 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.markdown +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.markdown @@ -70,9 +70,1047 @@ Fabric: Copyright 2018 Google, Inc. All Rights Reserved. Use of this software is Fabric: Copyright 2018 Google, Inc. All Rights Reserved. Use of this software is subject to the terms and conditions of the Fabric Software and Services Agreement located at https://fabric.io/terms. OSS: http://get.fabric.io/terms/opensource.txt -## GoogleAnalytics +## Firebase + +Copyright 2019 Google + +## FirebaseAnalytics + +Copyright 2019 Google + +## FirebaseAnalyticsInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCore + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstanceID + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseMessaging + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleAppMeasurement + +Copyright 2019 Google + +## GoogleUtilities + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -Copyright 2016 Google ## Instabug @@ -114,6 +1152,42 @@ SOFTWARE. +## Protobuf + +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + + ## SimulatorStatusMagic The MIT License (MIT) @@ -238,4 +1312,56 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## nanopb + +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + +## AppCenter + +Visual Studio App Center SDK for Apple platforms + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Generated by CocoaPods - https://cocoapods.org diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.plist b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.plist index bf0d8ff..7c74ba4 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.plist +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-acknowledgements.plist @@ -113,11 +113,1091 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI FooterText - Copyright 2016 Google + Copyright 2019 Google License Copyright Title - GoogleAnalytics + Firebase + Type + PSGroupSpecifier + + + FooterText + Copyright 2019 Google + License + Copyright + Title + FirebaseAnalytics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseAnalyticsInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCore + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstanceID + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseMessaging + Type + PSGroupSpecifier + + + FooterText + Copyright 2019 Google + License + Copyright + Title + GoogleAppMeasurement + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleUtilities Type PSGroupSpecifier @@ -173,6 +1253,48 @@ SOFTWARE. Type PSGroupSpecifier + + FooterText + Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + + License + 3-Clause BSD License + Title + Protobuf + Type + PSGroupSpecifier + FooterText The MIT License (MIT) @@ -328,6 +1450,70 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Type PSGroupSpecifier + + FooterText + Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi> + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + License + zlib + Title + nanopb + Type + PSGroupSpecifier + + + FooterText + Visual Studio App Center SDK for Apple platforms + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + License + MIT + Title + AppCenter + Type + PSGroupSpecifier + FooterText Generated by CocoaPods - https://cocoapods.org diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-frameworks.sh b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-frameworks.sh index a17d56d..89846f5 100755 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-frameworks.sh +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-frameworks.sh @@ -94,7 +94,7 @@ install_dsym() { binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then strip_invalid_archs "$binary" fi @@ -109,6 +109,14 @@ install_dsym() { fi } +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then @@ -156,38 +164,46 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" fi if [[ "$CONFIGURATION" == "Develop" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" fi if [[ "$CONFIGURATION" == "Sprint" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" fi if [[ "$CONFIGURATION" == "AppStore" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework" install_framework "${BUILT_PRODUCTS_DIR}/Anchorage/Anchorage.framework" install_framework "${BUILT_PRODUCTS_DIR}/BonMot/BonMot.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" install_framework "${PODS_ROOT}/Instabug/Instabug.framework" - install_dsym "${PODS_ROOT}/Instabug/Instabug.framework.dSYM" install_framework "${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework" install_framework "${BUILT_PRODUCTS_DIR}/Swiftilities/Swiftilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-resources.sh b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-resources.sh index fe3f9c7..1b5bde4 100755 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-resources.sh +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME-resources.sh @@ -3,10 +3,15 @@ set -e set -u set -o pipefail +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then - # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy - # resources to, so exit 0 (signalling the script phase was successful). - exit 0 + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 fi mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" @@ -91,6 +96,12 @@ EOM ;; esac } +if [[ "$CONFIGURATION" == "Develop" ]]; then + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/AppCenter/AppCenterDistributeResources.bundle" +fi +if [[ "$CONFIGURATION" == "Sprint" ]]; then + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/AppCenter/AppCenterDistributeResources.bundle" +fi mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" @@ -113,6 +124,6 @@ then if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" else - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" fi fi diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.appstore.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.appstore.xcconfig index 5599bb7..e588250 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.appstore.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.appstore.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Security" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Protobuf" -framework "Security" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.debug.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.debug.xcconfig index 4521f3b..27d82d4 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.debug.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.debug.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Security" -framework "SimulatorStatusMagic" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic/SimulatorStatusMagic.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SimulatorStatusMagic" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Protobuf" -framework "Security" -framework "SimulatorStatusMagic" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.develop.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.develop.xcconfig index 5599bb7..42ecb42 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.develop.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.develop.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Security" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "AppCenter" -framework "AppCenterDistribute" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Protobuf" -framework "Security" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "SafariServices" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.sprint.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.sprint.xcconfig index 5599bb7..42ecb42 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.sprint.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-PRODUCTNAME/Pods-PRODUCTNAME.sprint.xcconfig @@ -1,11 +1,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/Instabug" "$(PODS_ROOT)/Instabug/" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleAnalytics/Libraries" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "Fabric" -framework "Foundation" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Security" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/iOS" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_ROOT}/Crashlytics/iOS" -iframework "${PODS_ROOT}/Fabric/iOS" -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging" -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" -iframework "${PODS_ROOT}/Instabug" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Alamofire" -framework "Anchorage" -framework "AppCenter" -framework "AppCenterDistribute" -framework "BonMot" -framework "CoreData" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreVideo" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseInstanceID" -framework "FirebaseMessaging" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" -framework "Instabug" -framework "KeychainAccess" -framework "MessageUI" -framework "Protobuf" -framework "Security" -framework "StoreKit" -framework "Swiftilities" -framework "SystemConfiguration" -framework "UIKit" -framework "nanopb" -weak_framework "SafariServices" -weak_framework "UserNotifications" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.appstore.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.appstore.xcconfig index 042c073..34073b1 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.appstore.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.appstore.xcconfig @@ -1,6 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "Foundation" -framework "KeychainAccess" -framework "MessageUI" -framework "Swiftilities" -framework "UIKit" diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.debug.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.debug.xcconfig index 042c073..34073b1 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.debug.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.debug.xcconfig @@ -1,6 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "Foundation" -framework "KeychainAccess" -framework "MessageUI" -framework "Swiftilities" -framework "UIKit" diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.develop.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.develop.xcconfig index 042c073..34073b1 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.develop.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.develop.xcconfig @@ -1,6 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "Foundation" -framework "KeychainAccess" -framework "MessageUI" -framework "Swiftilities" -framework "UIKit" diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.sprint.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.sprint.xcconfig index 042c073..34073b1 100644 --- a/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.sprint.xcconfig +++ b/PRODUCTNAME/app/Pods/Target Support Files/Pods-Services/Pods-Services.sprint.xcconfig @@ -1,6 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GoogleAnalytics" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage/Anchorage.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/BonMot/BonMot.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities/Swiftilities.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Anchorage" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/BonMot" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Swiftilities" OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Anchorage" -framework "BonMot" -framework "CoreData" -framework "Foundation" -framework "KeychainAccess" -framework "MessageUI" -framework "Swiftilities" -framework "UIKit" diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-Info.plist new file mode 100644 index 0000000..3ef6a8d --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.7.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-dummy.m b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-dummy.m new file mode 100644 index 0000000..e0f0a33 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Protobuf : NSObject +@end +@implementation PodsDummy_Protobuf +@end diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-prefix.pch b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-umbrella.h b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-umbrella.h new file mode 100644 index 0000000..9242d72 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf-umbrella.h @@ -0,0 +1,54 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GPBArray.h" +#import "GPBArray_PackagePrivate.h" +#import "GPBBootstrap.h" +#import "GPBCodedInputStream.h" +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary.h" +#import "GPBDictionary_PackagePrivate.h" +#import "GPBExtensionInternals.h" +#import "GPBExtensionRegistry.h" +#import "GPBMessage.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBProtocolBuffers.h" +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "GPBRootObject.h" +#import "GPBRootObject_PackagePrivate.h" +#import "GPBRuntimeTypes.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFieldSet.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" +#import "GPBUtilities.h" +#import "GPBUtilities_PackagePrivate.h" +#import "GPBWellKnownTypes.h" +#import "GPBWireFormat.h" +#import "Any.pbobjc.h" +#import "Api.pbobjc.h" +#import "Duration.pbobjc.h" +#import "Empty.pbobjc.h" +#import "FieldMask.pbobjc.h" +#import "SourceContext.pbobjc.h" +#import "Struct.pbobjc.h" +#import "Timestamp.pbobjc.h" +#import "Type.pbobjc.h" +#import "Wrappers.pbobjc.h" + +FOUNDATION_EXPORT double ProtobufVersionNumber; +FOUNDATION_EXPORT const unsigned char ProtobufVersionString[]; + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf.modulemap b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf.modulemap new file mode 100644 index 0000000..57d3b39 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf.modulemap @@ -0,0 +1,6 @@ +framework module Protobuf { + umbrella header "Protobuf-umbrella.h" + + export * + module * { export * } +} diff --git a/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf.xcconfig new file mode 100644 index 0000000..12e3c31 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/Protobuf/Protobuf.xcconfig @@ -0,0 +1,8 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Protobuf +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Protobuf +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-Info.plist b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-Info.plist new file mode 100644 index 0000000..dbeb19f --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.3.901 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-dummy.m b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-dummy.m new file mode 100644 index 0000000..b3fa595 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_nanopb : NSObject +@end +@implementation PodsDummy_nanopb +@end diff --git a/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-prefix.pch b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-umbrella.h b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-umbrella.h new file mode 100644 index 0000000..07e77b3 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb-umbrella.h @@ -0,0 +1,26 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "pb.h" +#import "pb_common.h" +#import "pb_decode.h" +#import "pb_encode.h" +#import "pb.h" +#import "pb_decode.h" +#import "pb_common.h" +#import "pb.h" +#import "pb_encode.h" +#import "pb_common.h" + +FOUNDATION_EXPORT double nanopbVersionNumber; +FOUNDATION_EXPORT const unsigned char nanopbVersionString[]; + diff --git a/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb.modulemap b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb.modulemap new file mode 100644 index 0000000..e8d4b53 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb.modulemap @@ -0,0 +1,6 @@ +framework module nanopb { + umbrella header "nanopb-umbrella.h" + + export * + module * { export * } +} diff --git a/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb.xcconfig b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb.xcconfig new file mode 100644 index 0000000..704a532 --- /dev/null +++ b/PRODUCTNAME/app/Pods/Target Support Files/nanopb/nanopb.xcconfig @@ -0,0 +1,8 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/PRODUCTNAME/app/Pods/nanopb/LICENSE.txt b/PRODUCTNAME/app/Pods/nanopb/LICENSE.txt new file mode 100644 index 0000000..d11c9af --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. diff --git a/PRODUCTNAME/app/Pods/nanopb/README.md b/PRODUCTNAME/app/Pods/nanopb/README.md new file mode 100644 index 0000000..07860f0 --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/README.md @@ -0,0 +1,71 @@ +Nanopb - Protocol Buffers for Embedded Systems +============================================== + +[![Build Status](https://travis-ci.org/nanopb/nanopb.svg?branch=master)](https://travis-ci.org/nanopb/nanopb) + +Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is +especially suitable for use in microcontrollers, but fits any memory +restricted system. + +* **Homepage:** https://jpa.kapsi.fi/nanopb/ +* **Documentation:** https://jpa.kapsi.fi/nanopb/docs/ +* **Downloads:** https://jpa.kapsi.fi/nanopb/download/ +* **Forum:** https://groups.google.com/forum/#!forum/nanopb + + + +Using the nanopb library +------------------------ +To use the nanopb library, you need to do two things: + +1. Compile your .proto files for nanopb, using protoc. +2. Include pb_encode.c, pb_decode.c and pb_common.c in your project. + +The easiest way to get started is to study the project in "examples/simple". +It contains a Makefile, which should work directly under most Linux systems. +However, for any other kind of build system, see the manual steps in +README.txt in that folder. + + + +Using the Protocol Buffers compiler (protoc) +-------------------------------------------- +The nanopb generator is implemented as a plugin for the Google's own protoc +compiler. This has the advantage that there is no need to reimplement the +basic parsing of .proto files. However, it does mean that you need the +Google's protobuf library in order to run the generator. + +If you have downloaded a binary package for nanopb (either Windows, Linux or +Mac OS X version), the 'protoc' binary is included in the 'generator-bin' +folder. In this case, you are ready to go. Simply run this command: + + generator-bin/protoc --nanopb_out=. myprotocol.proto + +However, if you are using a git checkout or a plain source distribution, you +need to provide your own version of protoc and the Google's protobuf library. +On Linux, the necessary packages are protobuf-compiler and python-protobuf. +On Windows, you can either build Google's protobuf library from source or use +one of the binary distributions of it. In either case, if you use a separate +protoc, you need to manually give the path to nanopb generator: + + protoc --plugin=protoc-gen-nanopb=nanopb/generator/protoc-gen-nanopb ... + + + +Running the tests +----------------- +If you want to perform further development of the nanopb core, or to verify +its functionality using your compiler and platform, you'll want to run the +test suite. The build rules for the test suite are implemented using Scons, +so you need to have that installed. To run the tests: + + cd tests + scons + +This will show the progress of various test cases. If the output does not +end in an error, the test cases were successful. + +Note: Mac OS X by default aliases 'clang' as 'gcc', while not actually +supporting the same command line options as gcc does. To run tests on +Mac OS X, use: "scons CC=clang CXX=clang". Same way can be used to run +tests with different compilers on any platform. diff --git a/PRODUCTNAME/app/Pods/nanopb/pb.h b/PRODUCTNAME/app/Pods/nanopb/pb.h new file mode 100644 index 0000000..174a84b --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb.h @@ -0,0 +1,593 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +/* #define PB_FIELD_16BIT 1 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. */ +/* #define PB_OLD_CALLBACK_STYLE */ + + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION nanopb-0.3.9.1 + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif +#else +#define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x04 + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x05 + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x06 + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x07 + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x08 + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09 + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0A +#define PB_LTYPE_MASK 0x0F + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#elif defined(PB_FIELD_16BIT) + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#else + typedef uint_least8_t pb_size_t; + typedef int_least8_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. + */ +PB_PACKED_STRUCT_START +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. */ + const void *ptr; +} pb_packed; +PB_PACKED_STRUCT_END + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); + } funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; +#endif + + /* Free arg for use by callback */ + void *arg; +}; + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 30 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* data offset for subsequent fields inside an union (oneof) */ +#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ + ? PB_DATAOFFSET_FIRST(st, m1, m2) \ + : PB_DATAOFFSET_OTHER(st, m1, m2)) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. + */ +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. + * Furthermore, the combination of OPTIONAL without has_ field is used + * for indicating proto3 style fields. Extensions exist in proto2 mode only, + * so they should be encoded according to proto2 rules. To avoid the conflict, + * extensions are marked as REQUIRED instead. + */ +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} + +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) + +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC, CALLBACK or POINTER + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* Field description for repeated static fixed count fields.*/ +#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + 0, \ + pb_membersize(message, field[0]), \ + pb_arraysize(message, field), ptr} + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#endif diff --git a/PRODUCTNAME/app/Pods/nanopb/pb_common.c b/PRODUCTNAME/app/Pods/nanopb/pb_common.c new file mode 100644 index 0000000..4fb7186 --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb_common.c @@ -0,0 +1,97 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = fields; + iter->pos = fields; + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char*)dest_struct + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + + return (iter->pos->tag != 0); +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + const pb_field_t *prev_field = iter->pos; + + if (prev_field->tag == 0) + { + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. */ + return false; + } + + iter->pos++; + + if (iter->pos->tag == 0) + { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); + return false; + } + else + { + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && + iter->pos->data_offset == PB_SIZE_MAX) + { + /* Don't advance pointers inside unions */ + return true; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) + { + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries */ + prev_size *= prev_field->array_size; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) + { + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. */ + prev_size = sizeof(void*); + } + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + { + /* Count the required fields, in order to check their presence in the + * decoder. */ + iter->required_field_index++; + } + + iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + return true; + } +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + const pb_field_t *start = iter->pos; + + do { + if (iter->pos->tag == tag && + PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) + { + /* Found the wanted field */ + return true; + } + + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + /* Searched all the way back to start, and found nothing. */ + return false; +} + + diff --git a/PRODUCTNAME/app/Pods/nanopb/pb_common.h b/PRODUCTNAME/app/Pods/nanopb/pb_common.h new file mode 100644 index 0000000..60b3d37 --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb_common.h @@ -0,0 +1,42 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + unsigned required_field_index; /* Zero-based index that counts only the required fields */ + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/PRODUCTNAME/app/Pods/nanopb/pb_decode.c b/PRODUCTNAME/app/Pods/nanopb/pb_decode.c new file mode 100644 index 0000000..4b80e81 --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb_decode.c @@ -0,0 +1,1508 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL, /* extensions */ + &pb_dec_fixed_length_bytes +}; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + size_t i; + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + { + if (stream->bytes_left == 0) + { + if (eof) + { + *eof = true; + } + } + + return false; + } + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) + { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + else + { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) + { + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + return pb_read(stream, NULL, length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + { + return false; + } + + if (temp == 0) + { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) return false; + if (!pb_read(stream, buf, 1)) return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = size; + stream->bytes_left -= size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_OPTIONAL: + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < iter->pos->array_size) + { + void *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + (*size)++; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)iter->pSize; + char *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + + if ((*size)++ >= iter->pos->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return func(stream, iter->pos, pItem); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t*)iter->pSize = iter->pos->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(iter->pData, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData); + } + return func(stream, iter->pos, iter->pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || + PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(pItem, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(iter); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void**)iter->pData != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + pb_release_single_field(iter); + } + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = iter->pos->tag; + } + + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) + { + return func(stream, iter->pos, iter->pData); + } + else + { + if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1)) + return false; + + initialize_pointer_field(*(void**)iter->pData, iter); + return func(stream, iter->pos, *(void**)iter->pData); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + size_t allocated_size = *size; + void *pItem; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + allocated_size += (substream.bytes_left - 1) / iter->pos->data_size + 1; + + if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + pItem = *(char**)iter->pData + iter->pos->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + (*size)++; + if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size)) + return false; + + pItem = *(char**)iter->pData + iter->pos->data_size * (*size - 1); + initialize_pointer_field(pItem, iter); + return func(stream, iter->pos, pItem); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + +#ifdef PB_OLD_CALLBACK_STYLE + void *arg = pCallback->arg; +#else + void **arg = &(pCallback->arg); +#endif + + if (pCallback == NULL || pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + if (!pCallback->funcs.decode(&substream, iter->pos, arg)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->pos, arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, iter)) + return false; + } +#endif + + switch (PB_ATYPE(iter->pos->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + iter->pData = &extension->dest; + } +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + pb_field_iter_t iter; + + if (field->tag != tag) + return true; + + iter_from_extension(&iter, extension); + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + const pb_field_t *start = iter->pos; + + do { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static void pb_field_set_to_default(pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)iter->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)iter->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* Initialize submessage to defaults */ + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData); + } + else if (iter->pos->ptr != NULL) + { + /* Initialize to default value */ + memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size); + } + else + { + /* Initialize to zeros */ + memset(iter->pData, 0, iter->pos->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)iter->pData = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } +} + +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); +} + +/********************* + * Decode all fields * + *********************/ + +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + const uint32_t allbits = ~(uint32_t)0; + uint32_t extension_range_start = 0; + pb_field_iter_t iter; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + const pb_field_t *fixed_count_field = NULL; + pb_size_t fixed_count_size = 0; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (!pb_field_iter_find(&iter, tag)) + { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) + { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.pos->tag; + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED + && iter.pSize == iter.pData) + { + if (fixed_count_field != iter.pos) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + fixed_count_field = iter.pos; + fixed_count_size = 0; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + unsigned req_field_count; + pb_type_t last_type; + unsigned i; + do { + req_field_count = iter.required_field_index; + last_type = iter.pos->type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) + { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) + { + if (fields_seen[req_field_count >> 5] != + (allbits >> (32 - (req_field_count & 31)))) + { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + bool status; + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_noinit(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ + return pb_decode(stream, fields, dest_struct); +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) +{ + pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = iter->pos->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(iter, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(iter); + + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + + return true; +} + +static void pb_release_single_field(const pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)iter->pSize != iter->pos->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); + ext = ext->next; + } + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + pItem = *(void**)iter->pData; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) { + /* No _count field so use size of the array */ + count = iter->pos->array_size; + } else { + count = *(pb_size_t*)iter->pSize; + } + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size) + { + /* Protect against corrupted _count fields */ + count = iter->pos->array_size; + } + } + + if (pItem) + { + while (count--) + { + pb_release((const pb_field_t*)iter->pos->ptr, pItem); + pItem = (char*)pItem + iter->pos->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)iter->pData; + pb_size_t count = *(pb_size_t*)iter->pSize; + while (count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)iter->pSize = 0; + } + + /* Release main item */ + pb_free(*(void**)iter->pData); + *(void**)iter->pData = NULL; + } +} + +void pb_release(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[4]; + + if (!pb_read(stream, bytes, 4)) + return false; + + *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[8]; + + if (!pb_read(stream, bytes, 8)) + return false; + + *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + + return true; +} +#endif + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_int64_t value, clamped; + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} + +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_decode_fixed64(stream, dest); +#else + PB_UNUSED(dest); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *bdest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + bdest = *(pb_bytes_array_t**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + bdest = (pb_bytes_array_t*)dest; + } + + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + bool status; + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = size + 1; + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + dest = *(void**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + status = pb_read(stream, (pb_byte_t*)dest, size); + *((pb_byte_t*)dest + size) = 0; + return status; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + bool status; + pb_istream_t substream; + const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + status = pb_decode(&substream, submsg_fields, dest); + else + status = pb_decode_noinit(&substream, submsg_fields, dest); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) + { + /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ + memset(dest, 0, field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t*)dest, field->data_size); +} diff --git a/PRODUCTNAME/app/Pods/nanopb/pb_decode.h b/PRODUCTNAME/app/Pods/nanopb/pb_decode.h new file mode 100644 index 0000000..398b24a --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb_decode.h @@ -0,0 +1,175 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. + * + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. + * + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + */ +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode_delimited, except that it does not initialize the destination structure. + * See pb_decode_noinit + */ +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except allows the message to be terminated with a null byte. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour + * is not supported in most other protobuf implementations, so pb_decode_delimited() + * is a better option for compatibility. + */ +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_field_t fields[], void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * and uint32 field types. */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/PRODUCTNAME/app/Pods/nanopb/pb_encode.c b/PRODUCTNAME/app/Pods/nanopb/pb_encode.c new file mode 100644 index 0000000..089172c --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb_encode.c @@ -0,0 +1,869 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static void *pb_const_cast(const void *p); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t + +static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value); +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL, /* extensions */ + &pb_enc_fixed_length_bytes +}; + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + size_t i; + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + stream.callback = (void*)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (stream->callback != NULL) + { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) +{ + size_t i; + const void *p; + size_t size; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + p = pData; + for (i = 0; i < count; i++) + { + if (!func(&sizestream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + p = pData; + for (i = 0; i < count; i++) + { + if (!func(stream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + } + else + { + p = pData; + for (i = 0; i < count; i++) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + if (!func(stream, field, *(const void* const*)p)) + return false; + } + else + { + if (!func(stream, field, p)) + return false; + } + p = (const char*)p + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is "non-zero". + * This function implements the check for the zero value. */ +static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) +{ + pb_type_t type = field->type; + const void *pSize = (const char*)pData + field->size_offset; + + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) + { + /* Proto2 optional fields inside proto3 submessage */ + return *(const bool*)pSize == false; + } + + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) + { + do + { + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char*)pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + pb_encoder_t func; + bool implicit_has; + const void *pSize = &implicit_has; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) + { + /* Static optional, repeated or oneof field */ + pSize = (const char*)pData + field->size_offset; + } + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + { + /* Proto3 style field, optional but without explicit has_ field. */ + implicit_has = !pb_check_proto3_default_value(field, pData); + } + else + { + /* Required field, always present */ + implicit_has = true; + } + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + pData = *(const void* const*)pData; + implicit_has = (pData != NULL); + } + + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!func(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (*(const bool*)pSize) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: { + pb_size_t count; + if (field->size_offset != 0) { + count = *(const pb_size_t*)pSize; + } else { + count = field->array_size; + } + if (!encode_array(stream, field, pData, count, func)) + return false; + break; + } + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t*)pSize == field->tag) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return true; +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_callback_t *callback = (const pb_callback_t*)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) + { + if (!callback->funcs.encode(stream, field, arg)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + return encode_field(stream, field, &extension->dest); + } + else + { + return encode_field(stream, field, extension->dest); + } +} + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)pData; + PB_UNUSED(field); + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, iter.pos, iter.pData)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, iter.pos, iter.pData)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + return pb_encode_submessage(stream, fields, src_struct); +} + +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); +} + +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +#ifdef PB_WITHOUT_64BIT +bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */ + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + if (compensation) + { + /* re-set all the compensation bits we can or need */ + size_t bits = compensation > 7 ? 7 : compensation; + value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); /* set the number of bits needed on the lowest of the most significant 7 bits */ + compensation -= bits; + } + i++; + } + buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} +#endif + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + + if (value <= 0x7F) + { + pb_byte_t v = (pb_byte_t)value; + return pb_write(stream, &v, 1); + } + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; + } + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + +#ifdef PB_WITHOUT_64BIT + if (value < 0) + return pb_encode_negative_varint(stream, (pb_uint64_t)value); + else +#endif + return pb_encode_varint(stream, (pb_uint64_t)value); +} + +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)src; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} + +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_encode_fixed64(stream, src); +#else + PB_UNUSED(src); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t*)src; + + if (src == NULL) + { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + size_t size = 0; + size_t max_size = field->data_size; + const char *p = (const char*)src; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + max_size = (size_t)-1; + + if (src == NULL) + { + size = 0; /* Treat null pointer as an empty string */ + } + else + { + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + } + + return pb_encode_string(stream, (const pb_byte_t*)src, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); +} + diff --git a/PRODUCTNAME/app/Pods/nanopb/pb_encode.h b/PRODUCTNAME/app/Pods/nanopb/pb_encode.h new file mode 100644 index 0000000..8bf78dd --- /dev/null +++ b/PRODUCTNAME/app/Pods/nanopb/pb_encode.h @@ -0,0 +1,170 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. + */ +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but appends a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() + * is a better option for compatibility. + */ +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); + +/* Encode field header by manually specifing wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/PRODUCTNAME/app/fastlane/Fastfile b/PRODUCTNAME/app/fastlane/Fastfile index ff0129e..777e4e7 100644 --- a/PRODUCTNAME/app/fastlane/Fastfile +++ b/PRODUCTNAME/app/fastlane/Fastfile @@ -5,7 +5,6 @@ fastlane_require 'circleci_artifact' default_platform :ios # Set by build environment -# FL_HOCKEY_API_TOKEN # MATCH_PASSWORD # SLACK_URL - set the hook URL in the CircleCI environment @@ -14,8 +13,8 @@ ENV['RZ_TEST_REPORTS'] ||= ENV['CIRCLE_TEST_REPORTS'] || './build' ENV['FASTLANE_XCODE_LIST_TIMEOUT'] = '120' ENV['CI_BUILD'] = 'yes' ENV['GYM_OUTPUT_NAME'] = 'PRODUCTNAME' -ENV['FL_HOCKEY_IPA'] = "#{ENV['RZ_ARTIFACTS']}/#{ENV['GYM_OUTPUT_NAME']}.ipa" -ENV['FL_HOCKEY_NOTIFY'] = '0' +ENV['FL_APPCENTER_IPA'] = "#{ENV['RZ_ARTIFACTS']}/#{ENV['GYM_OUTPUT_NAME']}.ipa" +ENV['FL_APPCENTER_NOTIFY'] = '0' DERIVED_DATA_PATH = "#{ENV['RZ_TEST_REPORTS']}/derived_data" TEST_SCHEME = "debug-PRODUCTNAME" @@ -128,26 +127,40 @@ platform :ios do end end - desc "Builds and submits a Develop release to Hockey" + desc "Builds and submits a Develop release to AppCenter" lane :develop do match build("develop-PRODUCTNAME", 'enterprise', {}) - hockey(public_identifier: 'ZZHOCKEY_DEVELOP_IDZZ') + appcenter_upload( + api_token: ENV["APPCENTER_API_TOKEN"], + owner_name: ENV["APPCENTER_OWNER_NAME"], + app_name: "PRODUCTNAME-Develop", + ipa: ENV['FL_APPCENTER_IPA'], + destinations: "Internal", + destination_type: "group", + ) # upload_symbols_to_crashlytics(:api_token => 'ZZCRASHLYTICS_API_TOKEN_DEVELOPZZ') slack(message: "Successfully uploaded build #{build_number} to develop", success: true) end - desc "Builds and submits a Sprint release to Hockey" + desc "Builds and submits a Sprint release to AppCenter" lane :sprint do match build("sprint-PRODUCTNAME", 'enterprise', {}) - hockey(public_identifier: 'ZZHOCKEY_SPRINT_IDZZ') + appcenter_upload( + api_token: ENV["APPCENTER_API_TOKEN"], + owner_name: ENV["APPCENTER_OWNER_NAME"], + app_name: "PRODUCTNAME-Sprint", + ipa: ENV['FL_APPCENTER_IPA'], + destinations: "Internal", + destination_type: "group", + ) # upload_symbols_to_crashlytics(:api_token => 'ZZCRASHLYTICS_API_TOKEN_SPRINTZZ') slack(message: "Successfully uploaded build #{build_number} to sprint", success: true) end diff --git a/PRODUCTNAME/app/fastlane/Pluginfile b/PRODUCTNAME/app/fastlane/Pluginfile new file mode 100644 index 0000000..343fec8 --- /dev/null +++ b/PRODUCTNAME/app/fastlane/Pluginfile @@ -0,0 +1,6 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-install_provisioning_profiles' +gem 'fastlane-plugin-appcenter' diff --git a/PRODUCTNAME/app/fastlane/README.md b/PRODUCTNAME/app/fastlane/README.md index c5ad23f..7052f63 100644 --- a/PRODUCTNAME/app/fastlane/README.md +++ b/PRODUCTNAME/app/fastlane/README.md @@ -35,12 +35,12 @@ Posts screenshots to Slack ``` fastlane ios develop ``` -Builds and submits a Develop release to Hockey +Builds and submits a Develop release to AppCenter ### ios sprint ``` fastlane ios sprint ``` -Builds and submits a Sprint release to Hockey +Builds and submits a Sprint release to AppCenter ### ios beta ``` fastlane ios beta diff --git a/README.md b/README.md index 2bf266e..ecbacaa 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,6 @@ Pushing updates to this repository triggers CircleCI to build a blank template a ## What's in the template? - - Configures the project name, company name, lead name, an initial local repo, gitignore, and synx. - - Option to configure [Hockey][hockey] apps automatically. - [Default Fastfile][fastfile] with test, develop, sprint, beta and release lanes and slack notifications. - Configuration for [CircleCI][CircleCI] with auto-triggered builds for merges to develop or tags prefixed with sprint, beta or release. - [Danger](https://danger.systems) to automatically enforce conventions on every pull request. @@ -56,7 +54,6 @@ Pushing updates to this repository triggers CircleCI to build a blank template a [apiclient]: PRODUCTNAME/app/PRODUCTNAME/API [CircleCI]: PRODUCTNAME/circle.yml [swiftlint]: PRODUCTNAME/app/.swiftlint.yml -[hockey]: hooks/post_gen_project.sh [swiftgen]: https://github.com/SwiftGen/SwiftGen ## Contributing @@ -125,4 +122,4 @@ To [set up Danger](http://danger.systems/guides/getting_started.html) on CircleC Cookie Cutter is a python project for templating files and directories. Cookie cutter will ask a series of questions as defined in `cookiecutter.json` and then run the expansion on the contained files and directory names, and file contents. Anything with `{{ cookiecutter.variable }}` is expanded when the template is expanded. This is a powerful primitive but has some complications with Xcode ## Post processing -Cookie cutter follows a pattern of expand and prune, where the superset of the template is expanded, and then any specific functionality is pruned in a post in shell script `post_gen_project.sh`. You can also run shell scripts to integrate with web services. The included `post_gen_project.sh` is a good example of this, and it will create 2 apps on hockey and configure the `Fastfile`. +Cookie cutter follows a pattern of expand and prune, where the superset of the template is expanded, and then any specific functionality is pruned in a post in shell script `post_gen_project.sh`. You can also run shell scripts to integrate with web services. diff --git a/cookiecutter.json b/cookiecutter.json index 00a230f..61ee545 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -4,6 +4,7 @@ "bundle_identifier": "com.{{ cookiecutter.company_name | replace(' ', '-') | lower }}.{{ cookiecutter.project_name | replace(' ', '-') | lower }}", "lead_dev": "Your Name", "apple_id": "apple_id@rightpoint.com", - "hockey_key": "Ask a tech lead for the Hockey Key or enter NO", - "jira_key": "Specify the JIRA projectKey" + "jira_key": "Specify the JIRA projectKey", + "appcenter_org": "{{ cookiecutter.company_name | replace(' ', '-') }}", + "appcenter_app_name": "The name for the appcenter application" } diff --git a/generate_template.sh b/generate_template.sh index 9633f23..a0e6964 100755 --- a/generate_template.sh +++ b/generate_template.sh @@ -91,9 +91,11 @@ replace "PRODUCTNAME" "{{ cookiecutter.project_name | replace(' ', '') }}" replace "ORGANIZATION" "{{ cookiecutter.company_name }}" replace "LEADDEVELOPER" "{{ cookiecutter.lead_dev }}" replace "APPLEID" "{{ cookiecutter.apple_id }}" -replace "com.raizlabs.PRODUCTNAME" "{{ cookiecutter.bundle_identifier }}" +replace "com.rightpoint.PRODUCTNAME" "{{ cookiecutter.bundle_identifier }}" replace "THISYEAR" "{% now 'utc', '%Y' %}" replace "TODAYSDATE" "{% now 'utc', '%D' %}" +replace "APPCENTERORG" "{{ cookiecutter.appcenter_org }}" +replace "APPCENTERAPP" "{{ cookiecutter.appcenter_app_name | replace(' ', '-') }}" if [ "${SKIP_REGENERATION}" == "true" ] ; then echo "Dry run complete." diff --git a/hooks/post_gen_project.sh b/hooks/post_gen_project.sh index f6d672e..cddfa1f 100644 --- a/hooks/post_gen_project.sh +++ b/hooks/post_gen_project.sh @@ -6,21 +6,6 @@ git init bundle install cd app bundle exec pod install -if [[ "{{ cookiecutter.hockey_key }}" =~ .*[nN][oO].* ]] -then - echo "Skipping hockey app generation" -else - export DEVELOP_KEY=`curl -F "title={{ cookiecutter.project_name }}" -F "bundle_identifier={{ cookiecutter.bundle_identifier }}" -F "platform=iOS" -F "custom_release_type=Develop" -H "X-HockeyAppToken: {{ cookiecutter.hockey_key }}" https://rink.hockeyapp.net/api/2/apps/new | jq '.public_identifier' | sed -e 's/\"//g'` - echo "Hockey App Develop Key: $DEVELOP_KEY" - export SPRINT_KEY=`curl -F "title={{ cookiecutter.project_name }}" -F "bundle_identifier={{ cookiecutter.bundle_identifier }}" -F "platform=iOS" -F "custom_release_type=Sprint" -H "X-HockeyAppToken: {{ cookiecutter.hockey_key }}" https://rink.hockeyapp.net/api/2/apps/new | jq '.public_identifier' | sed -e 's/\"//g'` - echo "Hockey App Sprint Key: $DEVELOP_KEY" - perl -p -i -e "s/ZZHOCKEY_DEVELOP_IDZZ/$DEVELOP_KEY/g" fastlane/Fastfile - perl -p -i -e "s/ZZHOCKEY_SPRINT_IDZZ/$SPRINT_KEY/g" fastlane/Fastfile - echo "Fastfile updated" - perl -p -i -e "s/ZZHOCKEY_DEVELOP_IDZZ/$DEVELOP_KEY/g" ../README.md - perl -p -i -e "s/ZZHOCKEY_SPRINT_IDZZ/$SPRINT_KEY/g" ../README.md - echo "README updated" -fi bundle exec synx --no-sort-by-name "{{ cookiecutter.project_name | replace(' ', '') }}.xcodeproj" @@ -33,7 +18,7 @@ Congratulations! Please perform the following tasks: - Under "Settings -> Advanced Settings", turn on "Only build pull requests" - Configure Github - Protect "master" and "develop". Set "develop" as the default branch -- Ensure the Hockey Apps created have the correct teams +- Ensure the AppCenter Apps created have the correct teams - Review README.md architecture guidance - Make a PR against ios-template fixing any issues encountered - Update fastlane / Cocoapods in the Gemfile diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/Gemfile b/{{ cookiecutter.project_name | replace(' ', '') }}/Gemfile index 07552db..31931fc 100644 --- a/{{ cookiecutter.project_name | replace(' ', '') }}/Gemfile +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/Gemfile @@ -12,3 +12,6 @@ gem 'fastlane' gem 'cocoapods', '>=1.7.2' gem 'synx' gem 'nanaimo' + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/README.md index 4edbceb..0229e8d 100644 --- a/{{ cookiecutter.project_name | replace(' ', '') }}/README.md +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/README.md @@ -1,16 +1,14 @@ # {{ cookiecutter.project_name }} -[![Develop](https://img.shields.io/badge/Hockey-Develop-green.svg)][develop-hockey] -[![Sprint](https://img.shields.io/badge/Hockey-Sprint-green.svg)][sprint-hockey] +[![AppCenter](https://img.shields.io/badge/AppCenter-Yes-blue)](https://appcenter.ms/orgs/APPCENTERORG/apps/APPCENTERAPP) [![CircleCI](https://circleci.com/gh/Rightpoint/{{ cookiecutter.company_name | replace(' ', '-') | lower }}-ios/tree/develop.svg?style=shield&circle-token=ZZCIRCLE_PROJECT_STATUS_KEYZZ)][circle-ci] [![codecov](https://codecov.io/gh/Rightpoint/{{ cookiecutter.company_name | replace(' ', '-') | lower }}-ios/branch/master/graph/badge.svg)](https://codecov.io/gh/Rightpoint/{{ cookiecutter.company_name | replace(' ', '-') | lower }}-ios) ## Development Process -All stories and bugs are tracked in [JIRA][]. Development occurs on branches that are tested with the `test` fastlane task once a PR is created. The PR is reviewed and then merged into the `develop` branch. This triggers the `develop` fastlane task which distributes a build to the [develop][develop-hockey] hockey app for testing and PO approval. At the end of a sprint, a `sprint-X` tag is manually created which triggers the `sprint` fastlane task which distributes a build to the [sprint][sprint-hockey] hockey app. +All stories and bugs are tracked in [JIRA][]. Development occurs on branches that are tested with the `test` fastlane task once a PR is created. The PR is reviewed and then merged into the `develop` branch. This triggers the `develop` fastlane task which distributes a build to the [develop][develop-appcenter] Appcenter app for testing and PO approval. At the end of a sprint, a `sprint-X` tag is manually created which triggers the `sprint` fastlane task which distributes a build to the [sprint][sprint-appcenter] Appcenter app. -[circle-ci]: https://circleci.com/gh/Rightpoint/{{ cookiecutter.project_name }}-ios +[circle-ci]: https://circleci.com/gh/Rightpoint/{{ cookiecutter.project_name | replace(' ', '') }}-ios [JIRA]: https://raizlabs.atlassian.net/secure/RapidBoard.jspa?projectKey={{ cookiecutter.jira_key }} -[sprint-hockey]: https://rink.hockeyapp.net/apps/ZZHOCKEY_SPRINT_IDZZ -[develop-hockey]: https://rink.hockeyapp.net/apps/ZZHOCKEY_DEVELOP_IDZZ +[AppCenter]: https://appcenter.ms/orgs/APPCENTERORG/apps/APPCENTERAPP To get started, see [Contributing](#contributing) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile index fcc4786..f23c5e4 100644 --- a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile @@ -11,16 +11,23 @@ def shared pod 'Swiftilities' end +def firebase + pod 'Firebase/Core', :modular_headers => true + pod 'Firebase/Messaging', :modular_headers => true +end + target '{{ cookiecutter.project_name | replace(' ', '') }}' do pod 'Instabug' pod 'Crashlytics' - pod 'GoogleAnalytics', '~>3.0' + pod 'AppCenter/Distribute', :configurations => ['Sprint', 'Develop'] + firebase() pod 'SimulatorStatusMagic', :configurations => ['Debug'] target '{{ cookiecutter.project_name | replace(' ', '') }}Tests' do pod 'OHHTTPStubs/Swift' + firebase() end shared() diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile.lock b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile.lock new file mode 100644 index 0000000..491ed15 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Podfile.lock @@ -0,0 +1,227 @@ +PODS: + - Alamofire (4.8.2) + - Anchorage (4.3) + - AppCenter/Core (2.0.1) + - AppCenter/Distribute (2.0.1): + - AppCenter/Core + - BonMot (5.3) + - Crashlytics (3.12.0): + - Fabric (~> 1.9.0) + - Fabric (1.9.0) + - Firebase/Core (6.0.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.0.0) + - Firebase/CoreOnly (6.0.0): + - FirebaseCore (= 6.0.0) + - Firebase/Messaging (6.0.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 4.0.0) + - FirebaseAnalytics (6.0.0): + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleAppMeasurement (= 6.0.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - FirebaseAnalyticsInterop (1.2.0) + - FirebaseCore (6.0.0): + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Logger (~> 6.0) + - FirebaseInstanceID (4.0.0): + - FirebaseCore (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - FirebaseMessaging (4.0.0): + - FirebaseAnalyticsInterop (~> 1.1) + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Reachability (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - Protobuf (~> 3.1) + - GoogleAppMeasurement (6.0.0): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - GoogleUtilities/AppDelegateSwizzler (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.0.0) + - GoogleUtilities/Logger (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.0.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.0.0)" + - GoogleUtilities/Reachability (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.0.0): + - GoogleUtilities/Logger + - Instabug (8.3) + - KeychainAccess (3.2.0) + - nanopb (0.3.901): + - nanopb/decode (= 0.3.901) + - nanopb/encode (= 0.3.901) + - nanopb/decode (0.3.901) + - nanopb/encode (0.3.901) + - OHHTTPStubs/Core (8.0.0) + - OHHTTPStubs/Default (8.0.0): + - OHHTTPStubs/Core + - OHHTTPStubs/JSON + - OHHTTPStubs/NSURLSession + - OHHTTPStubs/OHPathHelpers + - OHHTTPStubs/JSON (8.0.0): + - OHHTTPStubs/Core + - OHHTTPStubs/NSURLSession (8.0.0): + - OHHTTPStubs/Core + - OHHTTPStubs/OHPathHelpers (8.0.0) + - OHHTTPStubs/Swift (8.0.0): + - OHHTTPStubs/Default + - Protobuf (3.7.0) + - SimulatorStatusMagic (2.4.1) + - Sourcery (0.16.1) + - SwiftGen (6.1.0) + - Swiftilities (0.22.1): + - Swiftilities/All (= 0.22.1) + - Swiftilities/AboutView (0.22.1) + - Swiftilities/AccessibilityHelpers (0.22.1) + - Swiftilities/Acknowledgements (0.22.1): + - Swiftilities/Compatibility + - Swiftilities/Deselection + - Swiftilities/LicenseFormatter + - Swiftilities/All (0.22.1): + - Swiftilities/AboutView + - Swiftilities/AccessibilityHelpers + - Swiftilities/Acknowledgements + - Swiftilities/BetterButton + - Swiftilities/ColorHelpers + - Swiftilities/Compatibility + - Swiftilities/CoreDataStack + - Swiftilities/Deselection + - Swiftilities/DeviceSize + - Swiftilities/FormattedTextField + - Swiftilities/Forms + - Swiftilities/HairlineView + - Swiftilities/ImageHelpers + - Swiftilities/Keyboard + - Swiftilities/LicenseFormatter + - Swiftilities/Lifecycle + - Swiftilities/Logging + - Swiftilities/Math + - Swiftilities/RootViewController + - Swiftilities/Shapes + - Swiftilities/StackViewHelpers + - Swiftilities/TableViewHelpers + - Swiftilities/TintedButton + - Swiftilities/Views + - Swiftilities/BetterButton (0.22.1): + - Swiftilities/ColorHelpers + - Swiftilities/ImageHelpers + - Swiftilities/Math + - Swiftilities/Shapes + - Swiftilities/ColorHelpers (0.22.1) + - Swiftilities/Compatibility (0.22.1) + - Swiftilities/CoreDataStack (0.22.1) + - Swiftilities/Deselection (0.22.1) + - Swiftilities/DeviceSize (0.22.1) + - Swiftilities/FormattedTextField (0.22.1) + - Swiftilities/Forms (0.22.1) + - Swiftilities/HairlineView (0.22.1) + - Swiftilities/ImageHelpers (0.22.1) + - Swiftilities/Keyboard (0.22.1) + - Swiftilities/LicenseFormatter (0.22.1) + - Swiftilities/Lifecycle (0.22.1): + - Swiftilities/HairlineView + - Swiftilities/Math + - Swiftilities/Logging (0.22.1) + - Swiftilities/Math (0.22.1) + - Swiftilities/RootViewController (0.22.1) + - Swiftilities/Shapes (0.22.1) + - Swiftilities/StackViewHelpers (0.22.1) + - Swiftilities/TableViewHelpers (0.22.1) + - Swiftilities/TintedButton (0.22.1) + - Swiftilities/Views (0.22.1) + - SwiftLint (0.32.0) + +DEPENDENCIES: + - Alamofire + - Anchorage + - AppCenter/Distribute + - BonMot + - Crashlytics + - Firebase/Core + - Firebase/Messaging + - Instabug + - KeychainAccess + - OHHTTPStubs/Swift + - SimulatorStatusMagic + - Sourcery (~> 0.16.1) + - SwiftGen + - Swiftilities + - SwiftLint + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - Alamofire + - Anchorage + - AppCenter + - BonMot + - Crashlytics + - Fabric + - Firebase + - FirebaseAnalytics + - FirebaseAnalyticsInterop + - FirebaseCore + - FirebaseInstanceID + - FirebaseMessaging + - GoogleAppMeasurement + - GoogleUtilities + - Instabug + - KeychainAccess + - nanopb + - OHHTTPStubs + - Protobuf + - SimulatorStatusMagic + - Sourcery + - SwiftGen + - Swiftilities + - SwiftLint + +SPEC CHECKSUMS: + Alamofire: ae5c501addb7afdbb13687d7f2f722c78734c2d3 + Anchorage: 21a98675245188427f0bcea21404d42a824a766f + AppCenter: 6a5ff2fd007b53431259fdd74f91eb3d0dfea3d1 + BonMot: 0104d1b4eda54f4a4b7393d6559539ef25498fbd + Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 + Fabric: f988e33c97f08930a413e08123064d2e5f68d655 + Firebase: fa80b9d987ca014a1ba9357496ef2a0178b28b12 + FirebaseAnalytics: 1743c5f4de3687d0745709dfdc4b1dea1484f44c + FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1 + FirebaseCore: e38f025287b413255a53acc1945d048a112047f7 + FirebaseInstanceID: 0e0348a3c00a734fa376a070f5ad4533ad975cb5 + FirebaseMessaging: c796d50864dc822a3c06c9c1c1444b37732b795b + GoogleAppMeasurement: 7f028ea162b72c8f326daec74afc95d94f7a47d6 + GoogleUtilities: f1faafc033ea203adf1783ce00af455bb99d0e5b + Instabug: c61ac1b653b64596c1bd00cf5ba039f05aecb930 + KeychainAccess: 3b1bf8a77eb4c6ea1ce9404c292e48f948954c6b + nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48 + OHHTTPStubs: 9cbce6364bec557cc3439aa6bb7514670d780881 + Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a + SimulatorStatusMagic: 28d4a9d1a500ac7cea0b2b5a43c1c6ddb40ba56c + Sourcery: 16779170d35ee204666843b09031f36721a84bcc + SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0 + Swiftilities: 7b57b06b46df20236a1cd9faf64ab3fd7554f4ed + SwiftLint: 009a898ef2a1c851f45e1b59349bf6ff2ddc990d + +PODFILE CHECKSUM: f4deff92cb777959f68cae8d4fd0677ec3f2443f + +COCOAPODS: 1.7.5 diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/LICENSE new file mode 100644 index 0000000..38a301a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/README.md new file mode 100644 index 0000000..26e364a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/README.md @@ -0,0 +1,243 @@ +![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/alamofire.png) + +[![Build Status](https://travis-ci.org/Alamofire/Alamofire.svg?branch=master)](https://travis-ci.org/Alamofire/Alamofire) +[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg)](https://img.shields.io/cocoapods/v/Alamofire.svg) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](https://alamofire.github.io/Alamofire) +[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat)](https://twitter.com/AlamofireSF) +[![Gitter](https://badges.gitter.im/Alamofire/Alamofire.svg)](https://gitter.im/Alamofire/Alamofire?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +Alamofire is an HTTP networking library written in Swift. + +- [Features](#features) +- [Component Libraries](#component-libraries) +- [Requirements](#requirements) +- [Migration Guides](#migration-guides) +- [Communication](#communication) +- [Installation](#installation) +- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md) + - **Intro -** [Making a Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#making-a-request), [Response Handling](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-handling), [Response Validation](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-validation), [Response Caching](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-caching) + - **HTTP -** [HTTP Methods](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods), [Parameter Encoding](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#parameter-encoding), [HTTP Headers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-headers), [Authentication](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#authentication) + - **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server) + - **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output) +- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md) + - **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-manager), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-delegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request) + - **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests) + - **Model Objects -** [Custom Response Serialization](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#custom-response-serialization) + - **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability) +- [Open Radars](#open-radars) +- [FAQ](#faq) +- [Credits](#credits) +- [Donations](#donations) +- [License](#license) + +## Features + +- [x] Chainable Request / Response Methods +- [x] URL / JSON / plist Parameter Encoding +- [x] Upload File / Data / Stream / MultipartFormData +- [x] Download File using Request or Resume Data +- [x] Authentication with URLCredential +- [x] HTTP Response Validation +- [x] Upload and Download Progress Closures with Progress +- [x] cURL Command Output +- [x] Dynamically Adapt and Retry Requests +- [x] TLS Certificate and Public Key Pinning +- [x] Network Reachability +- [x] Comprehensive Unit and Integration Test Coverage +- [x] [Complete Documentation](https://alamofire.github.io/Alamofire) + +## Component Libraries + +In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem. + +- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) - An image library including image response serializers, `UIImage` and `UIImageView` extensions, custom image filters, an auto-purging in-memory cache and a priority-based image downloading system. +- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) - Controls the visibility of the network activity indicator on iOS using Alamofire. It contains configurable delay timers to help mitigate flicker and can support `URLSession` instances not managed by Alamofire. + +## Requirements + +- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+ +- Xcode 8.3+ +- Swift 3.1+ + +## Migration Guides + +- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md) +- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md) +- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md) + +## Communication +- If you **need help with making network requests**, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`. +- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built. +- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire). +- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire). +- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire). +- If you **found a bug**, open an issue and follow the guide. The more detail the better! +- If you **want to contribute**, submit a pull request. + +## Installation + +### CocoaPods + +[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: + +```bash +$ gem install cocoapods +``` + +> CocoaPods 1.1+ is required to build Alamofire 4.0+. + +To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`: + +```ruby +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '10.0' +use_frameworks! + +target '' do + pod 'Alamofire', '~> 4.7' +end +``` + +Then, run the following command: + +```bash +$ pod install +``` + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. + +You can install Carthage with [Homebrew](https://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "Alamofire/Alamofire" ~> 4.7 +``` + +Run `carthage update` to build the framework and drag the built `Alamofire.framework` into your Xcode project. + +### Swift Package Manager + +The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Alamofire does support its use on supported platforms. + +Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`. + +#### Swift 3 + +```swift +dependencies: [ + .Package(url: "https://github.com/Alamofire/Alamofire.git", majorVersion: 4) +] +``` + +#### Swift 4 + +```swift +dependencies: [ + .package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.0.0") +] +``` + +### Manually + +If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually. + +#### Embedded Framework + +- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository: + + ```bash + $ git init + ``` + +- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command: + + ```bash + $ git submodule add https://github.com/Alamofire/Alamofire.git + ``` + +- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project. + + > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter. + +- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target. +- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar. +- In the tab bar at the top of that window, open the "General" panel. +- Click on the `+` button under the "Embedded Binaries" section. +- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder. + + > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`. + +- Select the top `Alamofire.framework` for iOS and the bottom one for OS X. + + > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as either `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS` or `Alamofire watchOS`. + +- And that's it! + + > The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device. + +## Open Radars + +The following radars have some effect on the current implementation of Alamofire. + +- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case +- `rdar://26870455` - Background URL Session Configurations do not work in the simulator +- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest` +- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+ + +## Resolved Radars + +The following radars have been resolved over time after being filed against the Alamofire project. + +- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage (Resolved on 9/1/17 in Xcode 9 beta 6). + +## FAQ + +### What's the origin of the name Alamofire? + +Alamofire is named after the [Alamo Fire flower](https://aggie-horticulture.tamu.edu/wildseed/alamofire.html), a hybrid variant of the Bluebonnet, the official state flower of Texas. + +### What logic belongs in a Router vs. a Request Adapter? + +Simple, static data such as paths, parameters and common headers belong in the `Router`. Dynamic data such as an `Authorization` header whose value can changed based on an authentication system belongs in a `RequestAdapter`. + +The reason the dynamic data MUST be placed into the `RequestAdapter` is to support retry operations. When a `Request` is retried, the original request is not rebuilt meaning the `Router` will not be called again. The `RequestAdapter` is called again allowing the dynamic data to be updated on the original request before retrying the `Request`. + +## Credits + +Alamofire is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). You can follow them on Twitter at [@AlamofireSF](https://twitter.com/AlamofireSF) for project updates and releases. + +### Security Disclosure + +If you believe you have identified a security vulnerability with Alamofire, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker. + +## Donations + +The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization. +Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax free. +Donating to the ASF will enable us to: + +- Pay our yearly legal fees to keep the non-profit in good status +- Pay for our mail servers to help us stay on top of all questions and security issues +- Potentially fund test servers to make it easier for us to test the edge cases +- Potentially fund developers to work on one of our projects full-time + +The community adoption of the ASF libraries has been amazing. +We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward. +With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members. +If you use any of our libraries for work, see if your employers would be interested in donating. +Any amount you can donate today to help us reach our goal would be greatly appreciated. + +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W34WPEE74APJQ) + +## License + +Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/AFError.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/AFError.swift new file mode 100644 index 0000000..b163f60 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/AFError.swift @@ -0,0 +1,460 @@ +// +// AFError.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with +/// their own associated reasons. +/// +/// - invalidURL: Returned when a `URLConvertible` type fails to create a valid `URL`. +/// - parameterEncodingFailed: Returned when a parameter encoding object throws an error during the encoding process. +/// - multipartEncodingFailed: Returned when some step in the multipart encoding process fails. +/// - responseValidationFailed: Returned when a `validate()` call fails. +/// - responseSerializationFailed: Returned when a response serializer encounters an error in the serialization process. +public enum AFError: Error { + /// The underlying reason the parameter encoding error occurred. + /// + /// - missingURL: The URL request did not have a URL to encode. + /// - jsonEncodingFailed: JSON serialization failed with an underlying system error during the + /// encoding process. + /// - propertyListEncodingFailed: Property list serialization failed with an underlying system error during + /// encoding process. + public enum ParameterEncodingFailureReason { + case missingURL + case jsonEncodingFailed(error: Error) + case propertyListEncodingFailed(error: Error) + } + + /// The underlying reason the multipart encoding error occurred. + /// + /// - bodyPartURLInvalid: The `fileURL` provided for reading an encodable body part isn't a + /// file URL. + /// - bodyPartFilenameInvalid: The filename of the `fileURL` provided has either an empty + /// `lastPathComponent` or `pathExtension. + /// - bodyPartFileNotReachable: The file at the `fileURL` provided was not reachable. + /// - bodyPartFileNotReachableWithError: Attempting to check the reachability of the `fileURL` provided threw + /// an error. + /// - bodyPartFileIsDirectory: The file at the `fileURL` provided is actually a directory. + /// - bodyPartFileSizeNotAvailable: The size of the file at the `fileURL` provided was not returned by + /// the system. + /// - bodyPartFileSizeQueryFailedWithError: The attempt to find the size of the file at the `fileURL` provided + /// threw an error. + /// - bodyPartInputStreamCreationFailed: An `InputStream` could not be created for the provided `fileURL`. + /// - outputStreamCreationFailed: An `OutputStream` could not be created when attempting to write the + /// encoded data to disk. + /// - outputStreamFileAlreadyExists: The encoded body data could not be writtent disk because a file + /// already exists at the provided `fileURL`. + /// - outputStreamURLInvalid: The `fileURL` provided for writing the encoded body data to disk is + /// not a file URL. + /// - outputStreamWriteFailed: The attempt to write the encoded body data to disk failed with an + /// underlying error. + /// - inputStreamReadFailed: The attempt to read an encoded body part `InputStream` failed with + /// underlying system error. + public enum MultipartEncodingFailureReason { + case bodyPartURLInvalid(url: URL) + case bodyPartFilenameInvalid(in: URL) + case bodyPartFileNotReachable(at: URL) + case bodyPartFileNotReachableWithError(atURL: URL, error: Error) + case bodyPartFileIsDirectory(at: URL) + case bodyPartFileSizeNotAvailable(at: URL) + case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error) + case bodyPartInputStreamCreationFailed(for: URL) + + case outputStreamCreationFailed(for: URL) + case outputStreamFileAlreadyExists(at: URL) + case outputStreamURLInvalid(url: URL) + case outputStreamWriteFailed(error: Error) + + case inputStreamReadFailed(error: Error) + } + + /// The underlying reason the response validation error occurred. + /// + /// - dataFileNil: The data file containing the server response did not exist. + /// - dataFileReadFailed: The data file containing the server response could not be read. + /// - missingContentType: The response did not contain a `Content-Type` and the `acceptableContentTypes` + /// provided did not contain wildcard type. + /// - unacceptableContentType: The response `Content-Type` did not match any type in the provided + /// `acceptableContentTypes`. + /// - unacceptableStatusCode: The response status code was not acceptable. + public enum ResponseValidationFailureReason { + case dataFileNil + case dataFileReadFailed(at: URL) + case missingContentType(acceptableContentTypes: [String]) + case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String) + case unacceptableStatusCode(code: Int) + } + + /// The underlying reason the response serialization error occurred. + /// + /// - inputDataNil: The server response contained no data. + /// - inputDataNilOrZeroLength: The server response contained no data or the data was zero length. + /// - inputFileNil: The file containing the server response did not exist. + /// - inputFileReadFailed: The file containing the server response could not be read. + /// - stringSerializationFailed: String serialization failed using the provided `String.Encoding`. + /// - jsonSerializationFailed: JSON serialization failed with an underlying system error. + /// - propertyListSerializationFailed: Property list serialization failed with an underlying system error. + public enum ResponseSerializationFailureReason { + case inputDataNil + case inputDataNilOrZeroLength + case inputFileNil + case inputFileReadFailed(at: URL) + case stringSerializationFailed(encoding: String.Encoding) + case jsonSerializationFailed(error: Error) + case propertyListSerializationFailed(error: Error) + } + + case invalidURL(url: URLConvertible) + case parameterEncodingFailed(reason: ParameterEncodingFailureReason) + case multipartEncodingFailed(reason: MultipartEncodingFailureReason) + case responseValidationFailed(reason: ResponseValidationFailureReason) + case responseSerializationFailed(reason: ResponseSerializationFailureReason) +} + +// MARK: - Adapt Error + +struct AdaptError: Error { + let error: Error +} + +extension Error { + var underlyingAdaptError: Error? { return (self as? AdaptError)?.error } +} + +// MARK: - Error Booleans + +extension AFError { + /// Returns whether the AFError is an invalid URL error. + public var isInvalidURLError: Bool { + if case .invalidURL = self { return true } + return false + } + + /// Returns whether the AFError is a parameter encoding error. When `true`, the `underlyingError` property will + /// contain the associated value. + public var isParameterEncodingError: Bool { + if case .parameterEncodingFailed = self { return true } + return false + } + + /// Returns whether the AFError is a multipart encoding error. When `true`, the `url` and `underlyingError` properties + /// will contain the associated values. + public var isMultipartEncodingError: Bool { + if case .multipartEncodingFailed = self { return true } + return false + } + + /// Returns whether the `AFError` is a response validation error. When `true`, the `acceptableContentTypes`, + /// `responseContentType`, and `responseCode` properties will contain the associated values. + public var isResponseValidationError: Bool { + if case .responseValidationFailed = self { return true } + return false + } + + /// Returns whether the `AFError` is a response serialization error. When `true`, the `failedStringEncoding` and + /// `underlyingError` properties will contain the associated values. + public var isResponseSerializationError: Bool { + if case .responseSerializationFailed = self { return true } + return false + } +} + +// MARK: - Convenience Properties + +extension AFError { + /// The `URLConvertible` associated with the error. + public var urlConvertible: URLConvertible? { + switch self { + case .invalidURL(let url): + return url + default: + return nil + } + } + + /// The `URL` associated with the error. + public var url: URL? { + switch self { + case .multipartEncodingFailed(let reason): + return reason.url + default: + return nil + } + } + + /// The `Error` returned by a system framework associated with a `.parameterEncodingFailed`, + /// `.multipartEncodingFailed` or `.responseSerializationFailed` error. + public var underlyingError: Error? { + switch self { + case .parameterEncodingFailed(let reason): + return reason.underlyingError + case .multipartEncodingFailed(let reason): + return reason.underlyingError + case .responseSerializationFailed(let reason): + return reason.underlyingError + default: + return nil + } + } + + /// The acceptable `Content-Type`s of a `.responseValidationFailed` error. + public var acceptableContentTypes: [String]? { + switch self { + case .responseValidationFailed(let reason): + return reason.acceptableContentTypes + default: + return nil + } + } + + /// The response `Content-Type` of a `.responseValidationFailed` error. + public var responseContentType: String? { + switch self { + case .responseValidationFailed(let reason): + return reason.responseContentType + default: + return nil + } + } + + /// The response code of a `.responseValidationFailed` error. + public var responseCode: Int? { + switch self { + case .responseValidationFailed(let reason): + return reason.responseCode + default: + return nil + } + } + + /// The `String.Encoding` associated with a failed `.stringResponse()` call. + public var failedStringEncoding: String.Encoding? { + switch self { + case .responseSerializationFailed(let reason): + return reason.failedStringEncoding + default: + return nil + } + } +} + +extension AFError.ParameterEncodingFailureReason { + var underlyingError: Error? { + switch self { + case .jsonEncodingFailed(let error), .propertyListEncodingFailed(let error): + return error + default: + return nil + } + } +} + +extension AFError.MultipartEncodingFailureReason { + var url: URL? { + switch self { + case .bodyPartURLInvalid(let url), .bodyPartFilenameInvalid(let url), .bodyPartFileNotReachable(let url), + .bodyPartFileIsDirectory(let url), .bodyPartFileSizeNotAvailable(let url), + .bodyPartInputStreamCreationFailed(let url), .outputStreamCreationFailed(let url), + .outputStreamFileAlreadyExists(let url), .outputStreamURLInvalid(let url), + .bodyPartFileNotReachableWithError(let url, _), .bodyPartFileSizeQueryFailedWithError(let url, _): + return url + default: + return nil + } + } + + var underlyingError: Error? { + switch self { + case .bodyPartFileNotReachableWithError(_, let error), .bodyPartFileSizeQueryFailedWithError(_, let error), + .outputStreamWriteFailed(let error), .inputStreamReadFailed(let error): + return error + default: + return nil + } + } +} + +extension AFError.ResponseValidationFailureReason { + var acceptableContentTypes: [String]? { + switch self { + case .missingContentType(let types), .unacceptableContentType(let types, _): + return types + default: + return nil + } + } + + var responseContentType: String? { + switch self { + case .unacceptableContentType(_, let responseType): + return responseType + default: + return nil + } + } + + var responseCode: Int? { + switch self { + case .unacceptableStatusCode(let code): + return code + default: + return nil + } + } +} + +extension AFError.ResponseSerializationFailureReason { + var failedStringEncoding: String.Encoding? { + switch self { + case .stringSerializationFailed(let encoding): + return encoding + default: + return nil + } + } + + var underlyingError: Error? { + switch self { + case .jsonSerializationFailed(let error), .propertyListSerializationFailed(let error): + return error + default: + return nil + } + } +} + +// MARK: - Error Descriptions + +extension AFError: LocalizedError { + public var errorDescription: String? { + switch self { + case .invalidURL(let url): + return "URL is not valid: \(url)" + case .parameterEncodingFailed(let reason): + return reason.localizedDescription + case .multipartEncodingFailed(let reason): + return reason.localizedDescription + case .responseValidationFailed(let reason): + return reason.localizedDescription + case .responseSerializationFailed(let reason): + return reason.localizedDescription + } + } +} + +extension AFError.ParameterEncodingFailureReason { + var localizedDescription: String { + switch self { + case .missingURL: + return "URL request to encode was missing a URL" + case .jsonEncodingFailed(let error): + return "JSON could not be encoded because of error:\n\(error.localizedDescription)" + case .propertyListEncodingFailed(let error): + return "PropertyList could not be encoded because of error:\n\(error.localizedDescription)" + } + } +} + +extension AFError.MultipartEncodingFailureReason { + var localizedDescription: String { + switch self { + case .bodyPartURLInvalid(let url): + return "The URL provided is not a file URL: \(url)" + case .bodyPartFilenameInvalid(let url): + return "The URL provided does not have a valid filename: \(url)" + case .bodyPartFileNotReachable(let url): + return "The URL provided is not reachable: \(url)" + case .bodyPartFileNotReachableWithError(let url, let error): + return ( + "The system returned an error while checking the provided URL for " + + "reachability.\nURL: \(url)\nError: \(error)" + ) + case .bodyPartFileIsDirectory(let url): + return "The URL provided is a directory: \(url)" + case .bodyPartFileSizeNotAvailable(let url): + return "Could not fetch the file size from the provided URL: \(url)" + case .bodyPartFileSizeQueryFailedWithError(let url, let error): + return ( + "The system returned an error while attempting to fetch the file size from the " + + "provided URL.\nURL: \(url)\nError: \(error)" + ) + case .bodyPartInputStreamCreationFailed(let url): + return "Failed to create an InputStream for the provided URL: \(url)" + case .outputStreamCreationFailed(let url): + return "Failed to create an OutputStream for URL: \(url)" + case .outputStreamFileAlreadyExists(let url): + return "A file already exists at the provided URL: \(url)" + case .outputStreamURLInvalid(let url): + return "The provided OutputStream URL is invalid: \(url)" + case .outputStreamWriteFailed(let error): + return "OutputStream write failed with error: \(error)" + case .inputStreamReadFailed(let error): + return "InputStream read failed with error: \(error)" + } + } +} + +extension AFError.ResponseSerializationFailureReason { + var localizedDescription: String { + switch self { + case .inputDataNil: + return "Response could not be serialized, input data was nil." + case .inputDataNilOrZeroLength: + return "Response could not be serialized, input data was nil or zero length." + case .inputFileNil: + return "Response could not be serialized, input file was nil." + case .inputFileReadFailed(let url): + return "Response could not be serialized, input file could not be read: \(url)." + case .stringSerializationFailed(let encoding): + return "String could not be serialized with encoding: \(encoding)." + case .jsonSerializationFailed(let error): + return "JSON could not be serialized because of error:\n\(error.localizedDescription)" + case .propertyListSerializationFailed(let error): + return "PropertyList could not be serialized because of error:\n\(error.localizedDescription)" + } + } +} + +extension AFError.ResponseValidationFailureReason { + var localizedDescription: String { + switch self { + case .dataFileNil: + return "Response could not be validated, data file was nil." + case .dataFileReadFailed(let url): + return "Response could not be validated, data file could not be read: \(url)." + case .missingContentType(let types): + return ( + "Response Content-Type was missing and acceptable content types " + + "(\(types.joined(separator: ","))) do not match \"*/*\"." + ) + case .unacceptableContentType(let acceptableTypes, let responseType): + return ( + "Response Content-Type \"\(responseType)\" does not match any acceptable types: " + + "\(acceptableTypes.joined(separator: ","))." + ) + case .unacceptableStatusCode(let code): + return "Response status code was unacceptable: \(code)." + } + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Alamofire.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Alamofire.swift new file mode 100644 index 0000000..20c3672 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Alamofire.swift @@ -0,0 +1,465 @@ +// +// Alamofire.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Types adopting the `URLConvertible` protocol can be used to construct URLs, which are then used to construct +/// URL requests. +public protocol URLConvertible { + /// Returns a URL that conforms to RFC 2396 or throws an `Error`. + /// + /// - throws: An `Error` if the type cannot be converted to a `URL`. + /// + /// - returns: A URL or throws an `Error`. + func asURL() throws -> URL +} + +extension String: URLConvertible { + /// Returns a URL if `self` represents a valid URL string that conforms to RFC 2396 or throws an `AFError`. + /// + /// - throws: An `AFError.invalidURL` if `self` is not a valid URL string. + /// + /// - returns: A URL or throws an `AFError`. + public func asURL() throws -> URL { + guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) } + return url + } +} + +extension URL: URLConvertible { + /// Returns self. + public func asURL() throws -> URL { return self } +} + +extension URLComponents: URLConvertible { + /// Returns a URL if `url` is not nil, otherwise throws an `Error`. + /// + /// - throws: An `AFError.invalidURL` if `url` is `nil`. + /// + /// - returns: A URL or throws an `AFError`. + public func asURL() throws -> URL { + guard let url = url else { throw AFError.invalidURL(url: self) } + return url + } +} + +// MARK: - + +/// Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests. +public protocol URLRequestConvertible { + /// Returns a URL request or throws if an `Error` was encountered. + /// + /// - throws: An `Error` if the underlying `URLRequest` is `nil`. + /// + /// - returns: A URL request. + func asURLRequest() throws -> URLRequest +} + +extension URLRequestConvertible { + /// The URL request. + public var urlRequest: URLRequest? { return try? asURLRequest() } +} + +extension URLRequest: URLRequestConvertible { + /// Returns a URL request or throws if an `Error` was encountered. + public func asURLRequest() throws -> URLRequest { return self } +} + +// MARK: - + +extension URLRequest { + /// Creates an instance with the specified `method`, `urlString` and `headers`. + /// + /// - parameter url: The URL. + /// - parameter method: The HTTP method. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The new `URLRequest` instance. + public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws { + let url = try url.asURL() + + self.init(url: url) + + httpMethod = method.rawValue + + if let headers = headers { + for (headerField, headerValue) in headers { + setValue(headerValue, forHTTPHeaderField: headerField) + } + } + } + + func adapt(using adapter: RequestAdapter?) throws -> URLRequest { + guard let adapter = adapter else { return self } + return try adapter.adapt(self) + } +} + +// MARK: - Data Request + +/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of the specified `url`, +/// `method`, `parameters`, `encoding` and `headers`. +/// +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.get` by default. +/// - parameter parameters: The parameters. `nil` by default. +/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `DataRequest`. +@discardableResult +public func request( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil) + -> DataRequest +{ + return SessionManager.default.request( + url, + method: method, + parameters: parameters, + encoding: encoding, + headers: headers + ) +} + +/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of a URL based on the +/// specified `urlRequest`. +/// +/// - parameter urlRequest: The URL request +/// +/// - returns: The created `DataRequest`. +@discardableResult +public func request(_ urlRequest: URLRequestConvertible) -> DataRequest { + return SessionManager.default.request(urlRequest) +} + +// MARK: - Download Request + +// MARK: URL Request + +/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of the specified `url`, +/// `method`, `parameters`, `encoding`, `headers` and save them to the `destination`. +/// +/// If `destination` is not specified, the contents will remain in the temporary location determined by the +/// underlying URL session. +/// +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.get` by default. +/// - parameter parameters: The parameters. `nil` by default. +/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. +/// +/// - returns: The created `DownloadRequest`. +@discardableResult +public func download( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest +{ + return SessionManager.default.download( + url, + method: method, + parameters: parameters, + encoding: encoding, + headers: headers, + to: destination + ) +} + +/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of a URL based on the +/// specified `urlRequest` and save them to the `destination`. +/// +/// If `destination` is not specified, the contents will remain in the temporary location determined by the +/// underlying URL session. +/// +/// - parameter urlRequest: The URL request. +/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. +/// +/// - returns: The created `DownloadRequest`. +@discardableResult +public func download( + _ urlRequest: URLRequestConvertible, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest +{ + return SessionManager.default.download(urlRequest, to: destination) +} + +// MARK: Resume Data + +/// Creates a `DownloadRequest` using the default `SessionManager` from the `resumeData` produced from a +/// previous request cancellation to retrieve the contents of the original request and save them to the `destination`. +/// +/// If `destination` is not specified, the contents will remain in the temporary location determined by the +/// underlying URL session. +/// +/// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken +/// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the +/// data is written incorrectly and will always fail to resume the download. For more information about the bug and +/// possible workarounds, please refer to the following Stack Overflow post: +/// +/// - http://stackoverflow.com/a/39347461/1342462 +/// +/// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask` +/// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for additional +/// information. +/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. +/// +/// - returns: The created `DownloadRequest`. +@discardableResult +public func download( + resumingWith resumeData: Data, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest +{ + return SessionManager.default.download(resumingWith: resumeData, to: destination) +} + +// MARK: - Upload Request + +// MARK: File + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers` +/// for uploading the `file`. +/// +/// - parameter file: The file to upload. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload( + _ fileURL: URL, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest +{ + return SessionManager.default.upload(fileURL, to: url, method: method, headers: headers) +} + +/// Creates a `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for +/// uploading the `file`. +/// +/// - parameter file: The file to upload. +/// - parameter urlRequest: The URL request. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest { + return SessionManager.default.upload(fileURL, with: urlRequest) +} + +// MARK: Data + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers` +/// for uploading the `data`. +/// +/// - parameter data: The data to upload. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload( + _ data: Data, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest +{ + return SessionManager.default.upload(data, to: url, method: method, headers: headers) +} + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for +/// uploading the `data`. +/// +/// - parameter data: The data to upload. +/// - parameter urlRequest: The URL request. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest { + return SessionManager.default.upload(data, with: urlRequest) +} + +// MARK: InputStream + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers` +/// for uploading the `stream`. +/// +/// - parameter stream: The stream to upload. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload( + _ stream: InputStream, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest +{ + return SessionManager.default.upload(stream, to: url, method: method, headers: headers) +} + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for +/// uploading the `stream`. +/// +/// - parameter urlRequest: The URL request. +/// - parameter stream: The stream to upload. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest { + return SessionManager.default.upload(stream, with: urlRequest) +} + +// MARK: MultipartFormData + +/// Encodes `multipartFormData` using `encodingMemoryThreshold` with the default `SessionManager` and calls +/// `encodingCompletion` with new `UploadRequest` using the `url`, `method` and `headers`. +/// +/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative +/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most +/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to +/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory +/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be +/// used for larger payloads such as video content. +/// +/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory +/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, +/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk +/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding +/// technique was used. +/// +/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. +/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. +/// `multipartFormDataEncodingMemoryThreshold` by default. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. +public func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil, + encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?) +{ + return SessionManager.default.upload( + multipartFormData: multipartFormData, + usingThreshold: encodingMemoryThreshold, + to: url, + method: method, + headers: headers, + encodingCompletion: encodingCompletion + ) +} + +/// Encodes `multipartFormData` using `encodingMemoryThreshold` and the default `SessionManager` and +/// calls `encodingCompletion` with new `UploadRequest` using the `urlRequest`. +/// +/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative +/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most +/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to +/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory +/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be +/// used for larger payloads such as video content. +/// +/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory +/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, +/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk +/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding +/// technique was used. +/// +/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. +/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. +/// `multipartFormDataEncodingMemoryThreshold` by default. +/// - parameter urlRequest: The URL request. +/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. +public func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + with urlRequest: URLRequestConvertible, + encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?) +{ + return SessionManager.default.upload( + multipartFormData: multipartFormData, + usingThreshold: encodingMemoryThreshold, + with: urlRequest, + encodingCompletion: encodingCompletion + ) +} + +#if !os(watchOS) + +// MARK: - Stream Request + +// MARK: Hostname and Port + +/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `hostname` +/// and `port`. +/// +/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. +/// +/// - parameter hostName: The hostname of the server to connect to. +/// - parameter port: The port of the server to connect to. +/// +/// - returns: The created `StreamRequest`. +@discardableResult +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +public func stream(withHostName hostName: String, port: Int) -> StreamRequest { + return SessionManager.default.stream(withHostName: hostName, port: port) +} + +// MARK: NetService + +/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `netService`. +/// +/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. +/// +/// - parameter netService: The net service used to identify the endpoint. +/// +/// - returns: The created `StreamRequest`. +@discardableResult +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +public func stream(with netService: NetService) -> StreamRequest { + return SessionManager.default.stream(with: netService) +} + +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift new file mode 100644 index 0000000..a54673c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift @@ -0,0 +1,37 @@ +// +// DispatchQueue+Alamofire.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Dispatch +import Foundation + +extension DispatchQueue { + static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) } + static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) } + static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) } + static var background: DispatchQueue { return DispatchQueue.global(qos: .background) } + + func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) { + asyncAfter(deadline: .now() + delay, execute: closure) + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/MultipartFormData.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/MultipartFormData.swift new file mode 100644 index 0000000..b840138 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/MultipartFormData.swift @@ -0,0 +1,580 @@ +// +// MultipartFormData.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +#if os(iOS) || os(watchOS) || os(tvOS) +import MobileCoreServices +#elseif os(macOS) +import CoreServices +#endif + +/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode +/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead +/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the +/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for +/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset. +/// +/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well +/// and the w3 form documentation. +/// +/// - https://www.ietf.org/rfc/rfc2388.txt +/// - https://www.ietf.org/rfc/rfc2045.txt +/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13 +open class MultipartFormData { + + // MARK: - Helper Types + + struct EncodingCharacters { + static let crlf = "\r\n" + } + + struct BoundaryGenerator { + enum BoundaryType { + case initial, encapsulated, final + } + + static func randomBoundary() -> String { + return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random()) + } + + static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data { + let boundaryText: String + + switch boundaryType { + case .initial: + boundaryText = "--\(boundary)\(EncodingCharacters.crlf)" + case .encapsulated: + boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)" + case .final: + boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)" + } + + return boundaryText.data(using: String.Encoding.utf8, allowLossyConversion: false)! + } + } + + class BodyPart { + let headers: HTTPHeaders + let bodyStream: InputStream + let bodyContentLength: UInt64 + var hasInitialBoundary = false + var hasFinalBoundary = false + + init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) { + self.headers = headers + self.bodyStream = bodyStream + self.bodyContentLength = bodyContentLength + } + } + + // MARK: - Properties + + /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`. + open lazy var contentType: String = "multipart/form-data; boundary=\(self.boundary)" + + /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries. + public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } } + + /// The boundary used to separate the body parts in the encoded form data. + public var boundary: String + + private var bodyParts: [BodyPart] + private var bodyPartError: AFError? + private let streamBufferSize: Int + + // MARK: - Lifecycle + + /// Creates a multipart form data object. + /// + /// - returns: The multipart form data object. + public init() { + self.boundary = BoundaryGenerator.randomBoundary() + self.bodyParts = [] + + /// + /// The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more + /// information, please refer to the following article: + /// - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html + /// + + self.streamBufferSize = 1024 + } + + // MARK: - Body Parts + + /// Creates a body part from the data and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}` (HTTP Header) + /// - Encoded data + /// - Multipart form boundary + /// + /// - parameter data: The data to encode into the multipart form data. + /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. + public func append(_ data: Data, withName name: String) { + let headers = contentHeaders(withName: name) + let stream = InputStream(data: data) + let length = UInt64(data.count) + + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part from the data and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}` (HTTP Header) + /// - `Content-Type: #{generated mimeType}` (HTTP Header) + /// - Encoded data + /// - Multipart form boundary + /// + /// - parameter data: The data to encode into the multipart form data. + /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the data content type in the `Content-Type` HTTP header. + public func append(_ data: Data, withName name: String, mimeType: String) { + let headers = contentHeaders(withName: name, mimeType: mimeType) + let stream = InputStream(data: data) + let length = UInt64(data.count) + + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part from the data and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header) + /// - `Content-Type: #{mimeType}` (HTTP Header) + /// - Encoded file data + /// - Multipart form boundary + /// + /// - parameter data: The data to encode into the multipart form data. + /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. + /// - parameter fileName: The filename to associate with the data in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header. + public func append(_ data: Data, withName name: String, fileName: String, mimeType: String) { + let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType) + let stream = InputStream(data: data) + let length = UInt64(data.count) + + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part from the file and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header) + /// - `Content-Type: #{generated mimeType}` (HTTP Header) + /// - Encoded file data + /// - Multipart form boundary + /// + /// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the + /// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the + /// system associated MIME type. + /// + /// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data. + /// - parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header. + public func append(_ fileURL: URL, withName name: String) { + let fileName = fileURL.lastPathComponent + let pathExtension = fileURL.pathExtension + + if !fileName.isEmpty && !pathExtension.isEmpty { + let mime = mimeType(forPathExtension: pathExtension) + append(fileURL, withName: name, fileName: fileName, mimeType: mime) + } else { + setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL)) + } + } + + /// Creates a body part from the file and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header) + /// - Content-Type: #{mimeType} (HTTP Header) + /// - Encoded file data + /// - Multipart form boundary + /// + /// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data. + /// - parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header. + /// - parameter fileName: The filename to associate with the file content in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the file content in the `Content-Type` HTTP header. + public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) { + let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType) + + //============================================================ + // Check 1 - is file URL? + //============================================================ + + guard fileURL.isFileURL else { + setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL)) + return + } + + //============================================================ + // Check 2 - is file URL reachable? + //============================================================ + + do { + let isReachable = try fileURL.checkPromisedItemIsReachable() + guard isReachable else { + setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL)) + return + } + } catch { + setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error)) + return + } + + //============================================================ + // Check 3 - is file URL a directory? + //============================================================ + + var isDirectory: ObjCBool = false + let path = fileURL.path + + guard FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else { + setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL)) + return + } + + //============================================================ + // Check 4 - can the file size be extracted? + //============================================================ + + let bodyContentLength: UInt64 + + do { + guard let fileSize = try FileManager.default.attributesOfItem(atPath: path)[.size] as? NSNumber else { + setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL)) + return + } + + bodyContentLength = fileSize.uint64Value + } + catch { + setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error)) + return + } + + //============================================================ + // Check 5 - can a stream be created from file URL? + //============================================================ + + guard let stream = InputStream(url: fileURL) else { + setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL)) + return + } + + append(stream, withLength: bodyContentLength, headers: headers) + } + + /// Creates a body part from the stream and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header) + /// - `Content-Type: #{mimeType}` (HTTP Header) + /// - Encoded stream data + /// - Multipart form boundary + /// + /// - parameter stream: The input stream to encode in the multipart form data. + /// - parameter length: The content length of the stream. + /// - parameter name: The name to associate with the stream content in the `Content-Disposition` HTTP header. + /// - parameter fileName: The filename to associate with the stream content in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the stream content in the `Content-Type` HTTP header. + public func append( + _ stream: InputStream, + withLength length: UInt64, + name: String, + fileName: String, + mimeType: String) + { + let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType) + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part with the headers, stream and length and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - HTTP headers + /// - Encoded stream data + /// - Multipart form boundary + /// + /// - parameter stream: The input stream to encode in the multipart form data. + /// - parameter length: The content length of the stream. + /// - parameter headers: The HTTP headers for the body part. + public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) { + let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length) + bodyParts.append(bodyPart) + } + + // MARK: - Data Encoding + + /// Encodes all the appended body parts into a single `Data` value. + /// + /// It is important to note that this method will load all the appended body parts into memory all at the same + /// time. This method should only be used when the encoded data will have a small memory footprint. For large data + /// cases, please use the `writeEncodedDataToDisk(fileURL:completionHandler:)` method. + /// + /// - throws: An `AFError` if encoding encounters an error. + /// + /// - returns: The encoded `Data` if encoding is successful. + public func encode() throws -> Data { + if let bodyPartError = bodyPartError { + throw bodyPartError + } + + var encoded = Data() + + bodyParts.first?.hasInitialBoundary = true + bodyParts.last?.hasFinalBoundary = true + + for bodyPart in bodyParts { + let encodedData = try encode(bodyPart) + encoded.append(encodedData) + } + + return encoded + } + + /// Writes the appended body parts into the given file URL. + /// + /// This process is facilitated by reading and writing with input and output streams, respectively. Thus, + /// this approach is very memory efficient and should be used for large body part data. + /// + /// - parameter fileURL: The file URL to write the multipart form data into. + /// + /// - throws: An `AFError` if encoding encounters an error. + public func writeEncodedData(to fileURL: URL) throws { + if let bodyPartError = bodyPartError { + throw bodyPartError + } + + if FileManager.default.fileExists(atPath: fileURL.path) { + throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL)) + } else if !fileURL.isFileURL { + throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL)) + } + + guard let outputStream = OutputStream(url: fileURL, append: false) else { + throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL)) + } + + outputStream.open() + defer { outputStream.close() } + + self.bodyParts.first?.hasInitialBoundary = true + self.bodyParts.last?.hasFinalBoundary = true + + for bodyPart in self.bodyParts { + try write(bodyPart, to: outputStream) + } + } + + // MARK: - Private - Body Part Encoding + + private func encode(_ bodyPart: BodyPart) throws -> Data { + var encoded = Data() + + let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData() + encoded.append(initialData) + + let headerData = encodeHeaders(for: bodyPart) + encoded.append(headerData) + + let bodyStreamData = try encodeBodyStream(for: bodyPart) + encoded.append(bodyStreamData) + + if bodyPart.hasFinalBoundary { + encoded.append(finalBoundaryData()) + } + + return encoded + } + + private func encodeHeaders(for bodyPart: BodyPart) -> Data { + var headerText = "" + + for (key, value) in bodyPart.headers { + headerText += "\(key): \(value)\(EncodingCharacters.crlf)" + } + headerText += EncodingCharacters.crlf + + return headerText.data(using: String.Encoding.utf8, allowLossyConversion: false)! + } + + private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data { + let inputStream = bodyPart.bodyStream + inputStream.open() + defer { inputStream.close() } + + var encoded = Data() + + while inputStream.hasBytesAvailable { + var buffer = [UInt8](repeating: 0, count: streamBufferSize) + let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize) + + if let error = inputStream.streamError { + throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error)) + } + + if bytesRead > 0 { + encoded.append(buffer, count: bytesRead) + } else { + break + } + } + + return encoded + } + + // MARK: - Private - Writing Body Part to Output Stream + + private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws { + try writeInitialBoundaryData(for: bodyPart, to: outputStream) + try writeHeaderData(for: bodyPart, to: outputStream) + try writeBodyStream(for: bodyPart, to: outputStream) + try writeFinalBoundaryData(for: bodyPart, to: outputStream) + } + + private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws { + let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData() + return try write(initialData, to: outputStream) + } + + private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws { + let headerData = encodeHeaders(for: bodyPart) + return try write(headerData, to: outputStream) + } + + private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws { + let inputStream = bodyPart.bodyStream + + inputStream.open() + defer { inputStream.close() } + + while inputStream.hasBytesAvailable { + var buffer = [UInt8](repeating: 0, count: streamBufferSize) + let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize) + + if let streamError = inputStream.streamError { + throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError)) + } + + if bytesRead > 0 { + if buffer.count != bytesRead { + buffer = Array(buffer[0.. 0, outputStream.hasSpaceAvailable { + let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite) + + if let error = outputStream.streamError { + throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error)) + } + + bytesToWrite -= bytesWritten + + if bytesToWrite > 0 { + buffer = Array(buffer[bytesWritten.. String { + if + let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(), + let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() + { + return contentType as String + } + + return "application/octet-stream" + } + + // MARK: - Private - Content Headers + + private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> [String: String] { + var disposition = "form-data; name=\"\(name)\"" + if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" } + + var headers = ["Content-Disposition": disposition] + if let mimeType = mimeType { headers["Content-Type"] = mimeType } + + return headers + } + + // MARK: - Private - Boundary Encoding + + private func initialBoundaryData() -> Data { + return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary) + } + + private func encapsulatedBoundaryData() -> Data { + return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary) + } + + private func finalBoundaryData() -> Data { + return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary) + } + + // MARK: - Private - Errors + + private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) { + guard bodyPartError == nil else { return } + bodyPartError = AFError.multipartEncodingFailed(reason: reason) + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/NetworkReachabilityManager.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/NetworkReachabilityManager.swift new file mode 100644 index 0000000..5470eec --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/NetworkReachabilityManager.swift @@ -0,0 +1,235 @@ +// +// NetworkReachabilityManager.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#if !os(watchOS) + +import Foundation +import SystemConfiguration + +/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and +/// WiFi network interfaces. +/// +/// Reachability can be used to determine background information about why a network operation failed, or to retry +/// network requests when a connection is established. It should not be used to prevent a user from initiating a network +/// request, as it's possible that an initial request may be required to establish reachability. +open class NetworkReachabilityManager { + /// Defines the various states of network reachability. + /// + /// - unknown: It is unknown whether the network is reachable. + /// - notReachable: The network is not reachable. + /// - reachable: The network is reachable. + public enum NetworkReachabilityStatus { + case unknown + case notReachable + case reachable(ConnectionType) + } + + /// Defines the various connection types detected by reachability flags. + /// + /// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi. + /// - wwan: The connection type is a WWAN connection. + public enum ConnectionType { + case ethernetOrWiFi + case wwan + } + + /// A closure executed when the network reachability status changes. The closure takes a single argument: the + /// network reachability status. + public typealias Listener = (NetworkReachabilityStatus) -> Void + + // MARK: - Properties + + /// Whether the network is currently reachable. + open var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi } + + /// Whether the network is currently reachable over the WWAN interface. + open var isReachableOnWWAN: Bool { return networkReachabilityStatus == .reachable(.wwan) } + + /// Whether the network is currently reachable over Ethernet or WiFi interface. + open var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .reachable(.ethernetOrWiFi) } + + /// The current network reachability status. + open var networkReachabilityStatus: NetworkReachabilityStatus { + guard let flags = self.flags else { return .unknown } + return networkReachabilityStatusForFlags(flags) + } + + /// The dispatch queue to execute the `listener` closure on. + open var listenerQueue: DispatchQueue = DispatchQueue.main + + /// A closure executed when the network reachability status changes. + open var listener: Listener? + + open var flags: SCNetworkReachabilityFlags? { + var flags = SCNetworkReachabilityFlags() + + if SCNetworkReachabilityGetFlags(reachability, &flags) { + return flags + } + + return nil + } + + private let reachability: SCNetworkReachability + open var previousFlags: SCNetworkReachabilityFlags + + // MARK: - Initialization + + /// Creates a `NetworkReachabilityManager` instance with the specified host. + /// + /// - parameter host: The host used to evaluate network reachability. + /// + /// - returns: The new `NetworkReachabilityManager` instance. + public convenience init?(host: String) { + guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil } + self.init(reachability: reachability) + } + + /// Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0. + /// + /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing + /// status of the device, both IPv4 and IPv6. + /// + /// - returns: The new `NetworkReachabilityManager` instance. + public convenience init?() { + var address = sockaddr_in() + address.sin_len = UInt8(MemoryLayout.size) + address.sin_family = sa_family_t(AF_INET) + + guard let reachability = withUnsafePointer(to: &address, { pointer in + return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout.size) { + return SCNetworkReachabilityCreateWithAddress(nil, $0) + } + }) else { return nil } + + self.init(reachability: reachability) + } + + private init(reachability: SCNetworkReachability) { + self.reachability = reachability + + // Set the previous flags to an unreserved value to represent unknown status + self.previousFlags = SCNetworkReachabilityFlags(rawValue: 1 << 30) + } + + deinit { + stopListening() + } + + // MARK: - Listening + + /// Starts listening for changes in network reachability status. + /// + /// - returns: `true` if listening was started successfully, `false` otherwise. + @discardableResult + open func startListening() -> Bool { + var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) + context.info = Unmanaged.passUnretained(self).toOpaque() + + let callbackEnabled = SCNetworkReachabilitySetCallback( + reachability, + { (_, flags, info) in + let reachability = Unmanaged.fromOpaque(info!).takeUnretainedValue() + reachability.notifyListener(flags) + }, + &context + ) + + let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue) + + listenerQueue.async { + guard let flags = self.flags else { return } + self.notifyListener(flags) + } + + return callbackEnabled && queueEnabled + } + + /// Stops listening for changes in network reachability status. + open func stopListening() { + SCNetworkReachabilitySetCallback(reachability, nil, nil) + SCNetworkReachabilitySetDispatchQueue(reachability, nil) + } + + // MARK: - Internal - Listener Notification + + func notifyListener(_ flags: SCNetworkReachabilityFlags) { + guard previousFlags != flags else { return } + previousFlags = flags + + listener?(networkReachabilityStatusForFlags(flags)) + } + + // MARK: - Internal - Network Reachability Status + + func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus { + guard isNetworkReachable(with: flags) else { return .notReachable } + + var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi) + + #if os(iOS) + if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) } + #endif + + return networkStatus + } + + func isNetworkReachable(with flags: SCNetworkReachabilityFlags) -> Bool { + let isReachable = flags.contains(.reachable) + let needsConnection = flags.contains(.connectionRequired) + let canConnectAutomatically = flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) + let canConnectWithoutUserInteraction = canConnectAutomatically && !flags.contains(.interventionRequired) + + return isReachable && (!needsConnection || canConnectWithoutUserInteraction) + } +} + +// MARK: - + +extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {} + +/// Returns whether the two network reachability status values are equal. +/// +/// - parameter lhs: The left-hand side value to compare. +/// - parameter rhs: The right-hand side value to compare. +/// +/// - returns: `true` if the two values are equal, `false` otherwise. +public func ==( + lhs: NetworkReachabilityManager.NetworkReachabilityStatus, + rhs: NetworkReachabilityManager.NetworkReachabilityStatus) + -> Bool +{ + switch (lhs, rhs) { + case (.unknown, .unknown): + return true + case (.notReachable, .notReachable): + return true + case let (.reachable(lhsConnectionType), .reachable(rhsConnectionType)): + return lhsConnectionType == rhsConnectionType + default: + return false + } +} + +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Notifications.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Notifications.swift new file mode 100644 index 0000000..e1ac31b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Notifications.swift @@ -0,0 +1,55 @@ +// +// Notifications.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +extension Notification.Name { + /// Used as a namespace for all `URLSessionTask` related notifications. + public struct Task { + /// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`. + public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume") + + /// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`. + public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend") + + /// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`. + public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel") + + /// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`. + public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete") + } +} + +// MARK: - + +extension Notification { + /// Used as a namespace for all `Notification` user info dictionary keys. + public struct Key { + /// User info dictionary key representing the `URLSessionTask` associated with the notification. + public static let Task = "org.alamofire.notification.key.task" + + /// User info dictionary key representing the responseData associated with the notification. + public static let ResponseData = "org.alamofire.notification.key.responseData" + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ParameterEncoding.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ParameterEncoding.swift new file mode 100644 index 0000000..6195809 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ParameterEncoding.swift @@ -0,0 +1,483 @@ +// +// ParameterEncoding.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// HTTP method definitions. +/// +/// See https://tools.ietf.org/html/rfc7231#section-4.3 +public enum HTTPMethod: String { + case options = "OPTIONS" + case get = "GET" + case head = "HEAD" + case post = "POST" + case put = "PUT" + case patch = "PATCH" + case delete = "DELETE" + case trace = "TRACE" + case connect = "CONNECT" +} + +// MARK: - + +/// A dictionary of parameters to apply to a `URLRequest`. +public typealias Parameters = [String: Any] + +/// A type used to define how a set of parameters are applied to a `URLRequest`. +public protocol ParameterEncoding { + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `AFError.parameterEncodingFailed` error if encoding fails. + /// + /// - returns: The encoded request. + func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest +} + +// MARK: - + +/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP +/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as +/// the HTTP body depends on the destination of the encoding. +/// +/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to +/// `application/x-www-form-urlencoded; charset=utf-8`. +/// +/// There is no published specification for how to encode collection types. By default the convention of appending +/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for +/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the +/// square brackets appended to array keys. +/// +/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode +/// `true` as 1 and `false` as 0. +public struct URLEncoding: ParameterEncoding { + + // MARK: Helper Types + + /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the + /// resulting URL request. + /// + /// - methodDependent: Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` + /// requests and sets as the HTTP body for requests with any other HTTP method. + /// - queryString: Sets or appends encoded query string result to existing query string. + /// - httpBody: Sets encoded query string result as the HTTP body of the URL request. + public enum Destination { + case methodDependent, queryString, httpBody + } + + /// Configures how `Array` parameters are encoded. + /// + /// - brackets: An empty set of square brackets is appended to the key for every value. + /// This is the default behavior. + /// - noBrackets: No brackets are appended. The key is encoded as is. + public enum ArrayEncoding { + case brackets, noBrackets + + func encode(key: String) -> String { + switch self { + case .brackets: + return "\(key)[]" + case .noBrackets: + return key + } + } + } + + /// Configures how `Bool` parameters are encoded. + /// + /// - numeric: Encode `true` as `1` and `false` as `0`. This is the default behavior. + /// - literal: Encode `true` and `false` as string literals. + public enum BoolEncoding { + case numeric, literal + + func encode(value: Bool) -> String { + switch self { + case .numeric: + return value ? "1" : "0" + case .literal: + return value ? "true" : "false" + } + } + } + + // MARK: Properties + + /// Returns a default `URLEncoding` instance. + public static var `default`: URLEncoding { return URLEncoding() } + + /// Returns a `URLEncoding` instance with a `.methodDependent` destination. + public static var methodDependent: URLEncoding { return URLEncoding() } + + /// Returns a `URLEncoding` instance with a `.queryString` destination. + public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) } + + /// Returns a `URLEncoding` instance with an `.httpBody` destination. + public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) } + + /// The destination defining where the encoded query string is to be applied to the URL request. + public let destination: Destination + + /// The encoding to use for `Array` parameters. + public let arrayEncoding: ArrayEncoding + + /// The encoding to use for `Bool` parameters. + public let boolEncoding: BoolEncoding + + // MARK: Initialization + + /// Creates a `URLEncoding` instance using the specified destination. + /// + /// - parameter destination: The destination defining where the encoded query string is to be applied. + /// - parameter arrayEncoding: The encoding to use for `Array` parameters. + /// - parameter boolEncoding: The encoding to use for `Bool` parameters. + /// + /// - returns: The new `URLEncoding` instance. + public init(destination: Destination = .methodDependent, arrayEncoding: ArrayEncoding = .brackets, boolEncoding: BoolEncoding = .numeric) { + self.destination = destination + self.arrayEncoding = arrayEncoding + self.boolEncoding = boolEncoding + } + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let parameters = parameters else { return urlRequest } + + if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) { + guard let url = urlRequest.url else { + throw AFError.parameterEncodingFailed(reason: .missingURL) + } + + if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { + let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) + urlComponents.percentEncodedQuery = percentEncodedQuery + urlRequest.url = urlComponents.url + } + } else { + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false) + } + + return urlRequest + } + + /// Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion. + /// + /// - parameter key: The key of the query component. + /// - parameter value: The value of the query component. + /// + /// - returns: The percent-escaped, URL encoded query string components. + public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] { + var components: [(String, String)] = [] + + if let dictionary = value as? [String: Any] { + for (nestedKey, value) in dictionary { + components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value) + } + } else if let array = value as? [Any] { + for value in array { + components += queryComponents(fromKey: arrayEncoding.encode(key: key), value: value) + } + } else if let value = value as? NSNumber { + if value.isBool { + components.append((escape(key), escape(boolEncoding.encode(value: value.boolValue)))) + } else { + components.append((escape(key), escape("\(value)"))) + } + } else if let bool = value as? Bool { + components.append((escape(key), escape(boolEncoding.encode(value: bool)))) + } else { + components.append((escape(key), escape("\(value)"))) + } + + return components + } + + /// Returns a percent-escaped string following RFC 3986 for a query string key or value. + /// + /// RFC 3986 states that the following characters are "reserved" characters. + /// + /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/" + /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" + /// + /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow + /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" + /// should be percent-escaped in the query string. + /// + /// - parameter string: The string to be percent-escaped. + /// + /// - returns: The percent-escaped string. + public func escape(_ string: String) -> String { + let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 + let subDelimitersToEncode = "!$&'()*+,;=" + + var allowedCharacterSet = CharacterSet.urlQueryAllowed + allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)") + + var escaped = "" + + //========================================================================================================== + // + // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few + // hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no + // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more + // info, please refer to: + // + // - https://github.com/Alamofire/Alamofire/issues/206 + // + //========================================================================================================== + + if #available(iOS 8.3, *) { + escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string + } else { + let batchSize = 50 + var index = string.startIndex + + while index != string.endIndex { + let startIndex = index + let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex + let range = startIndex.. String { + var components: [(String, String)] = [] + + for key in parameters.keys.sorted(by: <) { + let value = parameters[key]! + components += queryComponents(fromKey: key, value: value) + } + return components.map { "\($0)=\($1)" }.joined(separator: "&") + } + + private func encodesParametersInURL(with method: HTTPMethod) -> Bool { + switch destination { + case .queryString: + return true + case .httpBody: + return false + default: + break + } + + switch method { + case .get, .head, .delete: + return true + default: + return false + } + } +} + +// MARK: - + +/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the +/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`. +public struct JSONEncoding: ParameterEncoding { + + // MARK: Properties + + /// Returns a `JSONEncoding` instance with default writing options. + public static var `default`: JSONEncoding { return JSONEncoding() } + + /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options. + public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) } + + /// The options for writing the parameters as JSON data. + public let options: JSONSerialization.WritingOptions + + // MARK: Initialization + + /// Creates a `JSONEncoding` instance using the specified options. + /// + /// - parameter options: The options for writing the parameters as JSON data. + /// + /// - returns: The new `JSONEncoding` instance. + public init(options: JSONSerialization.WritingOptions = []) { + self.options = options + } + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let parameters = parameters else { return urlRequest } + + do { + let data = try JSONSerialization.data(withJSONObject: parameters, options: options) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = data + } catch { + throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) + } + + return urlRequest + } + + /// Creates a URL request by encoding the JSON object and setting the resulting data on the HTTP body. + /// + /// - parameter urlRequest: The request to apply the JSON object to. + /// - parameter jsonObject: The JSON object to apply to the request. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let jsonObject = jsonObject else { return urlRequest } + + do { + let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = data + } catch { + throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) + } + + return urlRequest + } +} + +// MARK: - + +/// Uses `PropertyListSerialization` to create a plist representation of the parameters object, according to the +/// associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header +/// field of an encoded request is set to `application/x-plist`. +public struct PropertyListEncoding: ParameterEncoding { + + // MARK: Properties + + /// Returns a default `PropertyListEncoding` instance. + public static var `default`: PropertyListEncoding { return PropertyListEncoding() } + + /// Returns a `PropertyListEncoding` instance with xml formatting and default writing options. + public static var xml: PropertyListEncoding { return PropertyListEncoding(format: .xml) } + + /// Returns a `PropertyListEncoding` instance with binary formatting and default writing options. + public static var binary: PropertyListEncoding { return PropertyListEncoding(format: .binary) } + + /// The property list serialization format. + public let format: PropertyListSerialization.PropertyListFormat + + /// The options for writing the parameters as plist data. + public let options: PropertyListSerialization.WriteOptions + + // MARK: Initialization + + /// Creates a `PropertyListEncoding` instance using the specified format and options. + /// + /// - parameter format: The property list serialization format. + /// - parameter options: The options for writing the parameters as plist data. + /// + /// - returns: The new `PropertyListEncoding` instance. + public init( + format: PropertyListSerialization.PropertyListFormat = .xml, + options: PropertyListSerialization.WriteOptions = 0) + { + self.format = format + self.options = options + } + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let parameters = parameters else { return urlRequest } + + do { + let data = try PropertyListSerialization.data( + fromPropertyList: parameters, + format: format, + options: options + ) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = data + } catch { + throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error)) + } + + return urlRequest + } +} + +// MARK: - + +extension NSNumber { + fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Request.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Request.swift new file mode 100644 index 0000000..a2efaa0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Request.swift @@ -0,0 +1,649 @@ +// +// Request.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary. +public protocol RequestAdapter { + /// Inspects and adapts the specified `URLRequest` in some manner if necessary and returns the result. + /// + /// - parameter urlRequest: The URL request to adapt. + /// + /// - throws: An `Error` if the adaptation encounters an error. + /// + /// - returns: The adapted `URLRequest`. + func adapt(_ urlRequest: URLRequest) throws -> URLRequest +} + +// MARK: - + +/// A closure executed when the `RequestRetrier` determines whether a `Request` should be retried or not. +public typealias RequestRetryCompletion = (_ shouldRetry: Bool, _ timeDelay: TimeInterval) -> Void + +/// A type that determines whether a request should be retried after being executed by the specified session manager +/// and encountering an error. +public protocol RequestRetrier { + /// Determines whether the `Request` should be retried by calling the `completion` closure. + /// + /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs + /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly + /// cleaned up after. + /// + /// - parameter manager: The session manager the request was executed on. + /// - parameter request: The request that failed due to the encountered error. + /// - parameter error: The error encountered when executing the request. + /// - parameter completion: The completion closure to be executed when retry decision has been determined. + func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) +} + +// MARK: - + +protocol TaskConvertible { + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask +} + +/// A dictionary of headers to apply to a `URLRequest`. +public typealias HTTPHeaders = [String: String] + +// MARK: - + +/// Responsible for sending a request and receiving the response and associated data from the server, as well as +/// managing its underlying `URLSessionTask`. +open class Request { + + // MARK: Helper Types + + /// A closure executed when monitoring upload or download progress of a request. + public typealias ProgressHandler = (Progress) -> Void + + enum RequestTask { + case data(TaskConvertible?, URLSessionTask?) + case download(TaskConvertible?, URLSessionTask?) + case upload(TaskConvertible?, URLSessionTask?) + case stream(TaskConvertible?, URLSessionTask?) + } + + // MARK: Properties + + /// The delegate for the underlying task. + open internal(set) var delegate: TaskDelegate { + get { + taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() } + return taskDelegate + } + set { + taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() } + taskDelegate = newValue + } + } + + /// The underlying task. + open var task: URLSessionTask? { return delegate.task } + + /// The session belonging to the underlying task. + public let session: URLSession + + /// The request sent or to be sent to the server. + open var request: URLRequest? { return task?.originalRequest } + + /// The response received from the server, if any. + open var response: HTTPURLResponse? { return task?.response as? HTTPURLResponse } + + /// The number of times the request has been retried. + open internal(set) var retryCount: UInt = 0 + + let originalTask: TaskConvertible? + + var startTime: CFAbsoluteTime? + var endTime: CFAbsoluteTime? + + var validations: [() -> Void] = [] + + private var taskDelegate: TaskDelegate + private var taskDelegateLock = NSLock() + + // MARK: Lifecycle + + init(session: URLSession, requestTask: RequestTask, error: Error? = nil) { + self.session = session + + switch requestTask { + case .data(let originalTask, let task): + taskDelegate = DataTaskDelegate(task: task) + self.originalTask = originalTask + case .download(let originalTask, let task): + taskDelegate = DownloadTaskDelegate(task: task) + self.originalTask = originalTask + case .upload(let originalTask, let task): + taskDelegate = UploadTaskDelegate(task: task) + self.originalTask = originalTask + case .stream(let originalTask, let task): + taskDelegate = TaskDelegate(task: task) + self.originalTask = originalTask + } + + delegate.error = error + delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() } + } + + // MARK: Authentication + + /// Associates an HTTP Basic credential with the request. + /// + /// - parameter user: The user. + /// - parameter password: The password. + /// - parameter persistence: The URL credential persistence. `.ForSession` by default. + /// + /// - returns: The request. + @discardableResult + open func authenticate( + user: String, + password: String, + persistence: URLCredential.Persistence = .forSession) + -> Self + { + let credential = URLCredential(user: user, password: password, persistence: persistence) + return authenticate(usingCredential: credential) + } + + /// Associates a specified credential with the request. + /// + /// - parameter credential: The credential. + /// + /// - returns: The request. + @discardableResult + open func authenticate(usingCredential credential: URLCredential) -> Self { + delegate.credential = credential + return self + } + + /// Returns a base64 encoded basic authentication credential as an authorization header tuple. + /// + /// - parameter user: The user. + /// - parameter password: The password. + /// + /// - returns: A tuple with Authorization header and credential value if encoding succeeds, `nil` otherwise. + open class func authorizationHeader(user: String, password: String) -> (key: String, value: String)? { + guard let data = "\(user):\(password)".data(using: .utf8) else { return nil } + + let credential = data.base64EncodedString(options: []) + + return (key: "Authorization", value: "Basic \(credential)") + } + + // MARK: State + + /// Resumes the request. + open func resume() { + guard let task = task else { delegate.queue.isSuspended = false ; return } + + if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() } + + task.resume() + + NotificationCenter.default.post( + name: Notification.Name.Task.DidResume, + object: self, + userInfo: [Notification.Key.Task: task] + ) + } + + /// Suspends the request. + open func suspend() { + guard let task = task else { return } + + task.suspend() + + NotificationCenter.default.post( + name: Notification.Name.Task.DidSuspend, + object: self, + userInfo: [Notification.Key.Task: task] + ) + } + + /// Cancels the request. + open func cancel() { + guard let task = task else { return } + + task.cancel() + + NotificationCenter.default.post( + name: Notification.Name.Task.DidCancel, + object: self, + userInfo: [Notification.Key.Task: task] + ) + } +} + +// MARK: - CustomStringConvertible + +extension Request: CustomStringConvertible { + /// The textual representation used when written to an output stream, which includes the HTTP method and URL, as + /// well as the response status code if a response has been received. + open var description: String { + var components: [String] = [] + + if let HTTPMethod = request?.httpMethod { + components.append(HTTPMethod) + } + + if let urlString = request?.url?.absoluteString { + components.append(urlString) + } + + if let response = response { + components.append("(\(response.statusCode))") + } + + return components.joined(separator: " ") + } +} + +// MARK: - CustomDebugStringConvertible + +extension Request: CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, in the form of a cURL command. + open var debugDescription: String { + return cURLRepresentation() + } + + func cURLRepresentation() -> String { + var components = ["$ curl -v"] + + guard let request = self.request, + let url = request.url, + let host = url.host + else { + return "$ curl command could not be created" + } + + if let httpMethod = request.httpMethod, httpMethod != "GET" { + components.append("-X \(httpMethod)") + } + + if let credentialStorage = self.session.configuration.urlCredentialStorage { + let protectionSpace = URLProtectionSpace( + host: host, + port: url.port ?? 0, + protocol: url.scheme, + realm: host, + authenticationMethod: NSURLAuthenticationMethodHTTPBasic + ) + + if let credentials = credentialStorage.credentials(for: protectionSpace)?.values { + for credential in credentials { + guard let user = credential.user, let password = credential.password else { continue } + components.append("-u \(user):\(password)") + } + } else { + if let credential = delegate.credential, let user = credential.user, let password = credential.password { + components.append("-u \(user):\(password)") + } + } + } + + if session.configuration.httpShouldSetCookies { + if + let cookieStorage = session.configuration.httpCookieStorage, + let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty + { + let string = cookies.reduce("") { $0 + "\($1.name)=\($1.value);" } + + #if swift(>=3.2) + components.append("-b \"\(string[.. URLSessionTask { + do { + let urlRequest = try self.urlRequest.adapt(using: adapter) + return queue.sync { session.dataTask(with: urlRequest) } + } catch { + throw AdaptError(error: error) + } + } + } + + // MARK: Properties + + /// The request sent or to be sent to the server. + open override var request: URLRequest? { + if let request = super.request { return request } + if let requestable = originalTask as? Requestable { return requestable.urlRequest } + + return nil + } + + /// The progress of fetching the response data from the server for the request. + open var progress: Progress { return dataDelegate.progress } + + var dataDelegate: DataTaskDelegate { return delegate as! DataTaskDelegate } + + // MARK: Stream + + /// Sets a closure to be called periodically during the lifecycle of the request as data is read from the server. + /// + /// This closure returns the bytes most recently received from the server, not including data from previous calls. + /// If this closure is set, data will only be available within this closure, and will not be saved elsewhere. It is + /// also important to note that the server data in any `Response` object will be `nil`. + /// + /// - parameter closure: The code to be executed periodically during the lifecycle of the request. + /// + /// - returns: The request. + @discardableResult + open func stream(closure: ((Data) -> Void)? = nil) -> Self { + dataDelegate.dataStream = closure + return self + } + + // MARK: Progress + + /// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server. + /// + /// - parameter queue: The dispatch queue to execute the closure on. + /// - parameter closure: The code to be executed periodically as data is read from the server. + /// + /// - returns: The request. + @discardableResult + open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self { + dataDelegate.progressHandler = (closure, queue) + return self + } +} + +// MARK: - + +/// Specific type of `Request` that manages an underlying `URLSessionDownloadTask`. +open class DownloadRequest: Request { + + // MARK: Helper Types + + /// A collection of options to be executed prior to moving a downloaded file from the temporary URL to the + /// destination URL. + public struct DownloadOptions: OptionSet { + /// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol. + public let rawValue: UInt + + /// A `DownloadOptions` flag that creates intermediate directories for the destination URL if specified. + public static let createIntermediateDirectories = DownloadOptions(rawValue: 1 << 0) + + /// A `DownloadOptions` flag that removes a previous file from the destination URL if specified. + public static let removePreviousFile = DownloadOptions(rawValue: 1 << 1) + + /// Creates a `DownloadFileDestinationOptions` instance with the specified raw value. + /// + /// - parameter rawValue: The raw bitmask value for the option. + /// + /// - returns: A new log level instance. + public init(rawValue: UInt) { + self.rawValue = rawValue + } + } + + /// A closure executed once a download request has successfully completed in order to determine where to move the + /// temporary file written to during the download process. The closure takes two arguments: the temporary file URL + /// and the URL response, and returns a two arguments: the file URL where the temporary file should be moved and + /// the options defining how the file should be moved. + public typealias DownloadFileDestination = ( + _ temporaryURL: URL, + _ response: HTTPURLResponse) + -> (destinationURL: URL, options: DownloadOptions) + + enum Downloadable: TaskConvertible { + case request(URLRequest) + case resumeData(Data) + + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask { + do { + let task: URLSessionTask + + switch self { + case let .request(urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.downloadTask(with: urlRequest) } + case let .resumeData(resumeData): + task = queue.sync { session.downloadTask(withResumeData: resumeData) } + } + + return task + } catch { + throw AdaptError(error: error) + } + } + } + + // MARK: Properties + + /// The request sent or to be sent to the server. + open override var request: URLRequest? { + if let request = super.request { return request } + + if let downloadable = originalTask as? Downloadable, case let .request(urlRequest) = downloadable { + return urlRequest + } + + return nil + } + + /// The resume data of the underlying download task if available after a failure. + open var resumeData: Data? { return downloadDelegate.resumeData } + + /// The progress of downloading the response data from the server for the request. + open var progress: Progress { return downloadDelegate.progress } + + var downloadDelegate: DownloadTaskDelegate { return delegate as! DownloadTaskDelegate } + + // MARK: State + + /// Cancels the request. + open override func cancel() { + downloadDelegate.downloadTask.cancel { self.downloadDelegate.resumeData = $0 } + + NotificationCenter.default.post( + name: Notification.Name.Task.DidCancel, + object: self, + userInfo: [Notification.Key.Task: task as Any] + ) + } + + // MARK: Progress + + /// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server. + /// + /// - parameter queue: The dispatch queue to execute the closure on. + /// - parameter closure: The code to be executed periodically as data is read from the server. + /// + /// - returns: The request. + @discardableResult + open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self { + downloadDelegate.progressHandler = (closure, queue) + return self + } + + // MARK: Destination + + /// Creates a download file destination closure which uses the default file manager to move the temporary file to a + /// file URL in the first available directory with the specified search path directory and search path domain mask. + /// + /// - parameter directory: The search path directory. `.DocumentDirectory` by default. + /// - parameter domain: The search path domain mask. `.UserDomainMask` by default. + /// + /// - returns: A download file destination closure. + open class func suggestedDownloadDestination( + for directory: FileManager.SearchPathDirectory = .documentDirectory, + in domain: FileManager.SearchPathDomainMask = .userDomainMask) + -> DownloadFileDestination + { + return { temporaryURL, response in + let directoryURLs = FileManager.default.urls(for: directory, in: domain) + + if !directoryURLs.isEmpty { + return (directoryURLs[0].appendingPathComponent(response.suggestedFilename!), []) + } + + return (temporaryURL, []) + } + } +} + +// MARK: - + +/// Specific type of `Request` that manages an underlying `URLSessionUploadTask`. +open class UploadRequest: DataRequest { + + // MARK: Helper Types + + enum Uploadable: TaskConvertible { + case data(Data, URLRequest) + case file(URL, URLRequest) + case stream(InputStream, URLRequest) + + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask { + do { + let task: URLSessionTask + + switch self { + case let .data(data, urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.uploadTask(with: urlRequest, from: data) } + case let .file(url, urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.uploadTask(with: urlRequest, fromFile: url) } + case let .stream(_, urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.uploadTask(withStreamedRequest: urlRequest) } + } + + return task + } catch { + throw AdaptError(error: error) + } + } + } + + // MARK: Properties + + /// The request sent or to be sent to the server. + open override var request: URLRequest? { + if let request = super.request { return request } + + guard let uploadable = originalTask as? Uploadable else { return nil } + + switch uploadable { + case .data(_, let urlRequest), .file(_, let urlRequest), .stream(_, let urlRequest): + return urlRequest + } + } + + /// The progress of uploading the payload to the server for the upload request. + open var uploadProgress: Progress { return uploadDelegate.uploadProgress } + + var uploadDelegate: UploadTaskDelegate { return delegate as! UploadTaskDelegate } + + // MARK: Upload Progress + + /// Sets a closure to be called periodically during the lifecycle of the `UploadRequest` as data is sent to + /// the server. + /// + /// After the data is sent to the server, the `progress(queue:closure:)` APIs can be used to monitor the progress + /// of data being read from the server. + /// + /// - parameter queue: The dispatch queue to execute the closure on. + /// - parameter closure: The code to be executed periodically as data is sent to the server. + /// + /// - returns: The request. + @discardableResult + open func uploadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self { + uploadDelegate.uploadProgressHandler = (closure, queue) + return self + } +} + +// MARK: - + +#if !os(watchOS) + +/// Specific type of `Request` that manages an underlying `URLSessionStreamTask`. +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +open class StreamRequest: Request { + enum Streamable: TaskConvertible { + case stream(hostName: String, port: Int) + case netService(NetService) + + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask { + let task: URLSessionTask + + switch self { + case let .stream(hostName, port): + task = queue.sync { session.streamTask(withHostName: hostName, port: port) } + case let .netService(netService): + task = queue.sync { session.streamTask(with: netService) } + } + + return task + } + } +} + +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Response.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Response.swift new file mode 100644 index 0000000..747a471 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Response.swift @@ -0,0 +1,567 @@ +// +// Response.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Used to store all data associated with an non-serialized response of a data or upload request. +public struct DefaultDataResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The data returned by the server. + public let data: Data? + + /// The error encountered while executing or validating the request. + public let error: Error? + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + var _metrics: AnyObject? + + /// Creates a `DefaultDataResponse` instance from the specified parameters. + /// + /// - Parameters: + /// - request: The URL request sent to the server. + /// - response: The server's response to the URL request. + /// - data: The data returned by the server. + /// - error: The error encountered while executing or validating the request. + /// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default. + /// - metrics: The task metrics containing the request / response statistics. `nil` by default. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + data: Data?, + error: Error?, + timeline: Timeline = Timeline(), + metrics: AnyObject? = nil) + { + self.request = request + self.response = response + self.data = data + self.error = error + self.timeline = timeline + } +} + +// MARK: - + +/// Used to store all data associated with a serialized response of a data or upload request. +public struct DataResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The data returned by the server. + public let data: Data? + + /// The result of response serialization. + public let result: Result + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + /// Returns the associated value of the result if it is a success, `nil` otherwise. + public var value: Value? { return result.value } + + /// Returns the associated error value if the result if it is a failure, `nil` otherwise. + public var error: Error? { return result.error } + + var _metrics: AnyObject? + + /// Creates a `DataResponse` instance with the specified parameters derived from response serialization. + /// + /// - parameter request: The URL request sent to the server. + /// - parameter response: The server's response to the URL request. + /// - parameter data: The data returned by the server. + /// - parameter result: The result of response serialization. + /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. + /// + /// - returns: The new `DataResponse` instance. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + data: Data?, + result: Result, + timeline: Timeline = Timeline()) + { + self.request = request + self.response = response + self.data = data + self.result = result + self.timeline = timeline + } +} + +// MARK: - + +extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, which includes whether the result was a + /// success or failure. + public var description: String { + return result.debugDescription + } + + /// The debug textual representation used when written to an output stream, which includes the URL request, the URL + /// response, the server data, the response serialization result and the timeline. + public var debugDescription: String { + var output: [String] = [] + + output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil") + output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") + output.append("[Data]: \(data?.count ?? 0) bytes") + output.append("[Result]: \(result.debugDescription)") + output.append("[Timeline]: \(timeline.debugDescription)") + + return output.joined(separator: "\n") + } +} + +// MARK: - + +extension DataResponse { + /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped + /// result value as a parameter. + /// + /// Use the `map` method with a closure that does not throw. For example: + /// + /// let possibleData: DataResponse = ... + /// let possibleInt = possibleData.map { $0.count } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's + /// result is a failure, returns a response wrapping the same failure. + public func map(_ transform: (Value) -> T) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.map(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result + /// value as a parameter. + /// + /// Use the `flatMap` method with a closure that may throw an error. For example: + /// + /// let possibleData: DataResponse = ... + /// let possibleObject = possibleData.flatMap { + /// try JSONSerialization.jsonObject(with: $0) + /// } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's + /// result is a failure, returns the same failure. + public func flatMap(_ transform: (Value) throws -> T) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.flatMap(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `mapError` function with a closure that does not throw. For example: + /// + /// let possibleData: DataResponse = ... + /// let withMyError = possibleData.mapError { MyError.error($0) } + /// + /// - Parameter transform: A closure that takes the error of the instance. + /// - Returns: A `DataResponse` instance containing the result of the transform. + public func mapError(_ transform: (Error) -> E) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.mapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `flatMapError` function with a closure that may throw an error. For example: + /// + /// let possibleData: DataResponse = ... + /// let possibleObject = possibleData.flatMapError { + /// try someFailableFunction(taking: $0) + /// } + /// + /// - Parameter transform: A throwing closure that takes the error of the instance. + /// + /// - Returns: A `DataResponse` instance containing the result of the transform. + public func flatMapError(_ transform: (Error) throws -> E) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.flatMapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } +} + +// MARK: - + +/// Used to store all data associated with an non-serialized response of a download request. +public struct DefaultDownloadResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The temporary destination URL of the data returned from the server. + public let temporaryURL: URL? + + /// The final destination URL of the data returned from the server if it was moved. + public let destinationURL: URL? + + /// The resume data generated if the request was cancelled. + public let resumeData: Data? + + /// The error encountered while executing or validating the request. + public let error: Error? + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + var _metrics: AnyObject? + + /// Creates a `DefaultDownloadResponse` instance from the specified parameters. + /// + /// - Parameters: + /// - request: The URL request sent to the server. + /// - response: The server's response to the URL request. + /// - temporaryURL: The temporary destination URL of the data returned from the server. + /// - destinationURL: The final destination URL of the data returned from the server if it was moved. + /// - resumeData: The resume data generated if the request was cancelled. + /// - error: The error encountered while executing or validating the request. + /// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default. + /// - metrics: The task metrics containing the request / response statistics. `nil` by default. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + temporaryURL: URL?, + destinationURL: URL?, + resumeData: Data?, + error: Error?, + timeline: Timeline = Timeline(), + metrics: AnyObject? = nil) + { + self.request = request + self.response = response + self.temporaryURL = temporaryURL + self.destinationURL = destinationURL + self.resumeData = resumeData + self.error = error + self.timeline = timeline + } +} + +// MARK: - + +/// Used to store all data associated with a serialized response of a download request. +public struct DownloadResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The temporary destination URL of the data returned from the server. + public let temporaryURL: URL? + + /// The final destination URL of the data returned from the server if it was moved. + public let destinationURL: URL? + + /// The resume data generated if the request was cancelled. + public let resumeData: Data? + + /// The result of response serialization. + public let result: Result + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + /// Returns the associated value of the result if it is a success, `nil` otherwise. + public var value: Value? { return result.value } + + /// Returns the associated error value if the result if it is a failure, `nil` otherwise. + public var error: Error? { return result.error } + + var _metrics: AnyObject? + + /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization. + /// + /// - parameter request: The URL request sent to the server. + /// - parameter response: The server's response to the URL request. + /// - parameter temporaryURL: The temporary destination URL of the data returned from the server. + /// - parameter destinationURL: The final destination URL of the data returned from the server if it was moved. + /// - parameter resumeData: The resume data generated if the request was cancelled. + /// - parameter result: The result of response serialization. + /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. + /// + /// - returns: The new `DownloadResponse` instance. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + temporaryURL: URL?, + destinationURL: URL?, + resumeData: Data?, + result: Result, + timeline: Timeline = Timeline()) + { + self.request = request + self.response = response + self.temporaryURL = temporaryURL + self.destinationURL = destinationURL + self.resumeData = resumeData + self.result = result + self.timeline = timeline + } +} + +// MARK: - + +extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, which includes whether the result was a + /// success or failure. + public var description: String { + return result.debugDescription + } + + /// The debug textual representation used when written to an output stream, which includes the URL request, the URL + /// response, the temporary and destination URLs, the resume data, the response serialization result and the + /// timeline. + public var debugDescription: String { + var output: [String] = [] + + output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil") + output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") + output.append("[TemporaryURL]: \(temporaryURL?.path ?? "nil")") + output.append("[DestinationURL]: \(destinationURL?.path ?? "nil")") + output.append("[ResumeData]: \(resumeData?.count ?? 0) bytes") + output.append("[Result]: \(result.debugDescription)") + output.append("[Timeline]: \(timeline.debugDescription)") + + return output.joined(separator: "\n") + } +} + +// MARK: - + +extension DownloadResponse { + /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped + /// result value as a parameter. + /// + /// Use the `map` method with a closure that does not throw. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let possibleInt = possibleData.map { $0.count } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's + /// result is a failure, returns a response wrapping the same failure. + public func map(_ transform: (Value) -> T) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.map(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped + /// result value as a parameter. + /// + /// Use the `flatMap` method with a closure that may throw an error. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let possibleObject = possibleData.flatMap { + /// try JSONSerialization.jsonObject(with: $0) + /// } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this + /// instance's result is a failure, returns the same failure. + public func flatMap(_ transform: (Value) throws -> T) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.flatMap(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `mapError` function with a closure that does not throw. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let withMyError = possibleData.mapError { MyError.error($0) } + /// + /// - Parameter transform: A closure that takes the error of the instance. + /// - Returns: A `DownloadResponse` instance containing the result of the transform. + public func mapError(_ transform: (Error) -> E) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.mapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `flatMapError` function with a closure that may throw an error. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let possibleObject = possibleData.flatMapError { + /// try someFailableFunction(taking: $0) + /// } + /// + /// - Parameter transform: A throwing closure that takes the error of the instance. + /// + /// - Returns: A `DownloadResponse` instance containing the result of the transform. + public func flatMapError(_ transform: (Error) throws -> E) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.flatMapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } +} + +// MARK: - + +protocol Response { + /// The task metrics containing the request / response statistics. + var _metrics: AnyObject? { get set } + mutating func add(_ metrics: AnyObject?) +} + +extension Response { + mutating func add(_ metrics: AnyObject?) { + #if !os(watchOS) + guard #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) else { return } + guard let metrics = metrics as? URLSessionTaskMetrics else { return } + + _metrics = metrics + #endif + } +} + +// MARK: - + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DefaultDataResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DataResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DefaultDownloadResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DownloadResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ResponseSerialization.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ResponseSerialization.swift new file mode 100644 index 0000000..9cc105a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ResponseSerialization.swift @@ -0,0 +1,715 @@ +// +// ResponseSerialization.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// The type in which all data response serializers must conform to in order to serialize a response. +public protocol DataResponseSerializerProtocol { + /// The type of serialized object to be created by this `DataResponseSerializerType`. + associatedtype SerializedObject + + /// A closure used by response handlers that takes a request, response, data and error and returns a result. + var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result { get } +} + +// MARK: - + +/// A generic `DataResponseSerializerType` used to serialize a request, response, and data into a serialized object. +public struct DataResponseSerializer: DataResponseSerializerProtocol { + /// The type of serialized object to be created by this `DataResponseSerializer`. + public typealias SerializedObject = Value + + /// A closure used by response handlers that takes a request, response, data and error and returns a result. + public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result + + /// Initializes the `ResponseSerializer` instance with the given serialize response closure. + /// + /// - parameter serializeResponse: The closure used to serialize the response. + /// + /// - returns: The new generic response serializer instance. + public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result) { + self.serializeResponse = serializeResponse + } +} + +// MARK: - + +/// The type in which all download response serializers must conform to in order to serialize a response. +public protocol DownloadResponseSerializerProtocol { + /// The type of serialized object to be created by this `DownloadResponseSerializerType`. + associatedtype SerializedObject + + /// A closure used by response handlers that takes a request, response, url and error and returns a result. + var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result { get } +} + +// MARK: - + +/// A generic `DownloadResponseSerializerType` used to serialize a request, response, and data into a serialized object. +public struct DownloadResponseSerializer: DownloadResponseSerializerProtocol { + /// The type of serialized object to be created by this `DownloadResponseSerializer`. + public typealias SerializedObject = Value + + /// A closure used by response handlers that takes a request, response, url and error and returns a result. + public var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result + + /// Initializes the `ResponseSerializer` instance with the given serialize response closure. + /// + /// - parameter serializeResponse: The closure used to serialize the response. + /// + /// - returns: The new generic response serializer instance. + public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result) { + self.serializeResponse = serializeResponse + } +} + +// MARK: - Timeline + +extension Request { + var timeline: Timeline { + let requestStartTime = self.startTime ?? CFAbsoluteTimeGetCurrent() + let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent() + let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime + + return Timeline( + requestStartTime: requestStartTime, + initialResponseTime: initialResponseTime, + requestCompletedTime: requestCompletedTime, + serializationCompletedTime: CFAbsoluteTimeGetCurrent() + ) + } +} + +// MARK: - Default + +extension DataRequest { + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self { + delegate.queue.addOperation { + (queue ?? DispatchQueue.main).async { + var dataResponse = DefaultDataResponse( + request: self.request, + response: self.response, + data: self.delegate.data, + error: self.delegate.error, + timeline: self.timeline + ) + + dataResponse.add(self.delegate.metrics) + + completionHandler(dataResponse) + } + } + + return self + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter responseSerializer: The response serializer responsible for serializing the request, response, + /// and data. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response( + queue: DispatchQueue? = nil, + responseSerializer: T, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + delegate.queue.addOperation { + let result = responseSerializer.serializeResponse( + self.request, + self.response, + self.delegate.data, + self.delegate.error + ) + + var dataResponse = DataResponse( + request: self.request, + response: self.response, + data: self.delegate.data, + result: result, + timeline: self.timeline + ) + + dataResponse.add(self.delegate.metrics) + + (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) } + } + + return self + } +} + +extension DownloadRequest { + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response( + queue: DispatchQueue? = nil, + completionHandler: @escaping (DefaultDownloadResponse) -> Void) + -> Self + { + delegate.queue.addOperation { + (queue ?? DispatchQueue.main).async { + var downloadResponse = DefaultDownloadResponse( + request: self.request, + response: self.response, + temporaryURL: self.downloadDelegate.temporaryURL, + destinationURL: self.downloadDelegate.destinationURL, + resumeData: self.downloadDelegate.resumeData, + error: self.downloadDelegate.error, + timeline: self.timeline + ) + + downloadResponse.add(self.delegate.metrics) + + completionHandler(downloadResponse) + } + } + + return self + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter responseSerializer: The response serializer responsible for serializing the request, response, + /// and data contained in the destination url. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response( + queue: DispatchQueue? = nil, + responseSerializer: T, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + delegate.queue.addOperation { + let result = responseSerializer.serializeResponse( + self.request, + self.response, + self.downloadDelegate.fileURL, + self.downloadDelegate.error + ) + + var downloadResponse = DownloadResponse( + request: self.request, + response: self.response, + temporaryURL: self.downloadDelegate.temporaryURL, + destinationURL: self.downloadDelegate.destinationURL, + resumeData: self.downloadDelegate.resumeData, + result: result, + timeline: self.timeline + ) + + downloadResponse.add(self.delegate.metrics) + + (queue ?? DispatchQueue.main).async { completionHandler(downloadResponse) } + } + + return self + } +} + +// MARK: - Data + +extension Request { + /// Returns a result data type that contains the response data as-is. + /// + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponseData(response: HTTPURLResponse?, data: Data?, error: Error?) -> Result { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(Data()) } + + guard let validData = data else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) + } + + return .success(validData) + } +} + +extension DataRequest { + /// Creates a response serializer that returns the associated data as-is. + /// + /// - returns: A data response serializer. + public static func dataResponseSerializer() -> DataResponseSerializer { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponseData(response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseData( + queue: DispatchQueue? = nil, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.dataResponseSerializer(), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns the associated data as-is. + /// + /// - returns: A data response serializer. + public static func dataResponseSerializer() -> DownloadResponseSerializer { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponseData(response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseData( + queue: DispatchQueue? = nil, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.dataResponseSerializer(), + completionHandler: completionHandler + ) + } +} + +// MARK: - String + +extension Request { + /// Returns a result string type initialized from the response data with the specified string encoding. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server + /// response, falling back to the default HTTP default character set, ISO-8859-1. + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponseString( + encoding: String.Encoding?, + response: HTTPURLResponse?, + data: Data?, + error: Error?) + -> Result + { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success("") } + + guard let validData = data else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) + } + + var convertedEncoding = encoding + + if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil { + convertedEncoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding( + CFStringConvertIANACharSetNameToEncoding(encodingName)) + ) + } + + let actualEncoding = convertedEncoding ?? .isoLatin1 + + if let string = String(data: validData, encoding: actualEncoding) { + return .success(string) + } else { + return .failure(AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))) + } + } +} + +extension DataRequest { + /// Creates a response serializer that returns a result string type initialized from the response data with + /// the specified string encoding. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server + /// response, falling back to the default HTTP default character set, ISO-8859-1. + /// + /// - returns: A string response serializer. + public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DataResponseSerializer { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the + /// server response, falling back to the default HTTP default character set, + /// ISO-8859-1. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseString( + queue: DispatchQueue? = nil, + encoding: String.Encoding? = nil, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns a result string type initialized from the response data with + /// the specified string encoding. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server + /// response, falling back to the default HTTP default character set, ISO-8859-1. + /// + /// - returns: A string response serializer. + public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DownloadResponseSerializer { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the + /// server response, falling back to the default HTTP default character set, + /// ISO-8859-1. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseString( + queue: DispatchQueue? = nil, + encoding: String.Encoding? = nil, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.stringResponseSerializer(encoding: encoding), + completionHandler: completionHandler + ) + } +} + +// MARK: - JSON + +extension Request { + /// Returns a JSON object contained in a result type constructed from the response data using `JSONSerialization` + /// with the specified reading options. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponseJSON( + options: JSONSerialization.ReadingOptions, + response: HTTPURLResponse?, + data: Data?, + error: Error?) + -> Result + { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) } + + guard let validData = data, validData.count > 0 else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)) + } + + do { + let json = try JSONSerialization.jsonObject(with: validData, options: options) + return .success(json) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))) + } + } +} + +extension DataRequest { + /// Creates a response serializer that returns a JSON object result type constructed from the response data using + /// `JSONSerialization` with the specified reading options. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// + /// - returns: A JSON object response serializer. + public static func jsonResponseSerializer( + options: JSONSerialization.ReadingOptions = .allowFragments) + -> DataResponseSerializer + { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponseJSON(options: options, response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseJSON( + queue: DispatchQueue? = nil, + options: JSONSerialization.ReadingOptions = .allowFragments, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.jsonResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns a JSON object result type constructed from the response data using + /// `JSONSerialization` with the specified reading options. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// + /// - returns: A JSON object response serializer. + public static func jsonResponseSerializer( + options: JSONSerialization.ReadingOptions = .allowFragments) + -> DownloadResponseSerializer + { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponseJSON(options: options, response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseJSON( + queue: DispatchQueue? = nil, + options: JSONSerialization.ReadingOptions = .allowFragments, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.jsonResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +// MARK: - Property List + +extension Request { + /// Returns a plist object contained in a result type constructed from the response data using + /// `PropertyListSerialization` with the specified reading options. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponsePropertyList( + options: PropertyListSerialization.ReadOptions, + response: HTTPURLResponse?, + data: Data?, + error: Error?) + -> Result + { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) } + + guard let validData = data, validData.count > 0 else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)) + } + + do { + let plist = try PropertyListSerialization.propertyList(from: validData, options: options, format: nil) + return .success(plist) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .propertyListSerializationFailed(error: error))) + } + } +} + +extension DataRequest { + /// Creates a response serializer that returns an object constructed from the response data using + /// `PropertyListSerialization` with the specified reading options. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// + /// - returns: A property list object response serializer. + public static func propertyListResponseSerializer( + options: PropertyListSerialization.ReadOptions = []) + -> DataResponseSerializer + { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responsePropertyList( + queue: DispatchQueue? = nil, + options: PropertyListSerialization.ReadOptions = [], + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.propertyListResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns an object constructed from the response data using + /// `PropertyListSerialization` with the specified reading options. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// + /// - returns: A property list object response serializer. + public static func propertyListResponseSerializer( + options: PropertyListSerialization.ReadOptions = []) + -> DownloadResponseSerializer + { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responsePropertyList( + queue: DispatchQueue? = nil, + options: PropertyListSerialization.ReadOptions = [], + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.propertyListResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +/// A set of HTTP response status code that do not contain response data. +private let emptyDataStatusCodes: Set = [204, 205] diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Result.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Result.swift new file mode 100644 index 0000000..e092808 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Result.swift @@ -0,0 +1,300 @@ +// +// Result.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Used to represent whether a request was successful or encountered an error. +/// +/// - success: The request and all post processing operations were successful resulting in the serialization of the +/// provided associated value. +/// +/// - failure: The request encountered an error resulting in a failure. The associated values are the original data +/// provided by the server as well as the error that caused the failure. +public enum Result { + case success(Value) + case failure(Error) + + /// Returns `true` if the result is a success, `false` otherwise. + public var isSuccess: Bool { + switch self { + case .success: + return true + case .failure: + return false + } + } + + /// Returns `true` if the result is a failure, `false` otherwise. + public var isFailure: Bool { + return !isSuccess + } + + /// Returns the associated value if the result is a success, `nil` otherwise. + public var value: Value? { + switch self { + case .success(let value): + return value + case .failure: + return nil + } + } + + /// Returns the associated error value if the result is a failure, `nil` otherwise. + public var error: Error? { + switch self { + case .success: + return nil + case .failure(let error): + return error + } + } +} + +// MARK: - CustomStringConvertible + +extension Result: CustomStringConvertible { + /// The textual representation used when written to an output stream, which includes whether the result was a + /// success or failure. + public var description: String { + switch self { + case .success: + return "SUCCESS" + case .failure: + return "FAILURE" + } + } +} + +// MARK: - CustomDebugStringConvertible + +extension Result: CustomDebugStringConvertible { + /// The debug textual representation used when written to an output stream, which includes whether the result was a + /// success or failure in addition to the value or error. + public var debugDescription: String { + switch self { + case .success(let value): + return "SUCCESS: \(value)" + case .failure(let error): + return "FAILURE: \(error)" + } + } +} + +// MARK: - Functional APIs + +extension Result { + /// Creates a `Result` instance from the result of a closure. + /// + /// A failure result is created when the closure throws, and a success result is created when the closure + /// succeeds without throwing an error. + /// + /// func someString() throws -> String { ... } + /// + /// let result = Result(value: { + /// return try someString() + /// }) + /// + /// // The type of result is Result + /// + /// The trailing closure syntax is also supported: + /// + /// let result = Result { try someString() } + /// + /// - parameter value: The closure to execute and create the result for. + public init(value: () throws -> Value) { + do { + self = try .success(value()) + } catch { + self = .failure(error) + } + } + + /// Returns the success value, or throws the failure error. + /// + /// let possibleString: Result = .success("success") + /// try print(possibleString.unwrap()) + /// // Prints "success" + /// + /// let noString: Result = .failure(error) + /// try print(noString.unwrap()) + /// // Throws error + public func unwrap() throws -> Value { + switch self { + case .success(let value): + return value + case .failure(let error): + throw error + } + } + + /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. + /// + /// Use the `map` method with a closure that does not throw. For example: + /// + /// let possibleData: Result = .success(Data()) + /// let possibleInt = possibleData.map { $0.count } + /// try print(possibleInt.unwrap()) + /// // Prints "0" + /// + /// let noData: Result = .failure(error) + /// let noInt = noData.map { $0.count } + /// try print(noInt.unwrap()) + /// // Throws error + /// + /// - parameter transform: A closure that takes the success value of the `Result` instance. + /// + /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the + /// same failure. + public func map(_ transform: (Value) -> T) -> Result { + switch self { + case .success(let value): + return .success(transform(value)) + case .failure(let error): + return .failure(error) + } + } + + /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. + /// + /// Use the `flatMap` method with a closure that may throw an error. For example: + /// + /// let possibleData: Result = .success(Data(...)) + /// let possibleObject = possibleData.flatMap { + /// try JSONSerialization.jsonObject(with: $0) + /// } + /// + /// - parameter transform: A closure that takes the success value of the instance. + /// + /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the + /// same failure. + public func flatMap(_ transform: (Value) throws -> T) -> Result { + switch self { + case .success(let value): + do { + return try .success(transform(value)) + } catch { + return .failure(error) + } + case .failure(let error): + return .failure(error) + } + } + + /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `mapError` function with a closure that does not throw. For example: + /// + /// let possibleData: Result = .failure(someError) + /// let withMyError: Result = possibleData.mapError { MyError.error($0) } + /// + /// - Parameter transform: A closure that takes the error of the instance. + /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns + /// the same instance. + public func mapError(_ transform: (Error) -> T) -> Result { + switch self { + case .failure(let error): + return .failure(transform(error)) + case .success: + return self + } + } + + /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `flatMapError` function with a closure that may throw an error. For example: + /// + /// let possibleData: Result = .success(Data(...)) + /// let possibleObject = possibleData.flatMapError { + /// try someFailableFunction(taking: $0) + /// } + /// + /// - Parameter transform: A throwing closure that takes the error of the instance. + /// + /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns + /// the same instance. + public func flatMapError(_ transform: (Error) throws -> T) -> Result { + switch self { + case .failure(let error): + do { + return try .failure(transform(error)) + } catch { + return .failure(error) + } + case .success: + return self + } + } + + /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. + /// + /// Use the `withValue` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A closure that takes the success value of this instance. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func withValue(_ closure: (Value) throws -> Void) rethrows -> Result { + if case let .success(value) = self { try closure(value) } + + return self + } + + /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `withError` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A closure that takes the success value of this instance. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func withError(_ closure: (Error) throws -> Void) rethrows -> Result { + if case let .failure(error) = self { try closure(error) } + + return self + } + + /// Evaluates the specified closure when the `Result` is a success. + /// + /// Use the `ifSuccess` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A `Void` closure. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func ifSuccess(_ closure: () throws -> Void) rethrows -> Result { + if isSuccess { try closure() } + + return self + } + + /// Evaluates the specified closure when the `Result` is a failure. + /// + /// Use the `ifFailure` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A `Void` closure. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func ifFailure(_ closure: () throws -> Void) rethrows -> Result { + if isFailure { try closure() } + + return self + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ServerTrustPolicy.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ServerTrustPolicy.swift new file mode 100644 index 0000000..dea099e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/ServerTrustPolicy.swift @@ -0,0 +1,307 @@ +// +// ServerTrustPolicy.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host. +open class ServerTrustPolicyManager { + /// The dictionary of policies mapped to a particular host. + public let policies: [String: ServerTrustPolicy] + + /// Initializes the `ServerTrustPolicyManager` instance with the given policies. + /// + /// Since different servers and web services can have different leaf certificates, intermediate and even root + /// certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This + /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key + /// pinning for host3 and disabling evaluation for host4. + /// + /// - parameter policies: A dictionary of all policies mapped to a particular host. + /// + /// - returns: The new `ServerTrustPolicyManager` instance. + public init(policies: [String: ServerTrustPolicy]) { + self.policies = policies + } + + /// Returns the `ServerTrustPolicy` for the given host if applicable. + /// + /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override + /// this method and implement more complex mapping implementations such as wildcards. + /// + /// - parameter host: The host to use when searching for a matching policy. + /// + /// - returns: The server trust policy for the given host if found. + open func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? { + return policies[host] + } +} + +// MARK: - + +extension URLSession { + private struct AssociatedKeys { + static var managerKey = "URLSession.ServerTrustPolicyManager" + } + + var serverTrustPolicyManager: ServerTrustPolicyManager? { + get { + return objc_getAssociatedObject(self, &AssociatedKeys.managerKey) as? ServerTrustPolicyManager + } + set (manager) { + objc_setAssociatedObject(self, &AssociatedKeys.managerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } +} + +// MARK: - ServerTrustPolicy + +/// The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when +/// connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust +/// with a given set of criteria to determine whether the server trust is valid and the connection should be made. +/// +/// Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other +/// vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged +/// to route all communication over an HTTPS connection with pinning enabled. +/// +/// - performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to +/// validate the host provided by the challenge. Applications are encouraged to always +/// validate the host in production environments to guarantee the validity of the server's +/// certificate chain. +/// +/// - performRevokedEvaluation: Uses the default and revoked server trust evaluations allowing you to control whether to +/// validate the host provided by the challenge as well as specify the revocation flags for +/// testing for revoked certificates. Apple platforms did not start testing for revoked +/// certificates automatically until iOS 10.1, macOS 10.12 and tvOS 10.1 which is +/// demonstrated in our TLS tests. Applications are encouraged to always validate the host +/// in production environments to guarantee the validity of the server's certificate chain. +/// +/// - pinCertificates: Uses the pinned certificates to validate the server trust. The server trust is +/// considered valid if one of the pinned certificates match one of the server certificates. +/// By validating both the certificate chain and host, certificate pinning provides a very +/// secure form of server trust validation mitigating most, if not all, MITM attacks. +/// Applications are encouraged to always validate the host and require a valid certificate +/// chain in production environments. +/// +/// - pinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered +/// valid if one of the pinned public keys match one of the server certificate public keys. +/// By validating both the certificate chain and host, public key pinning provides a very +/// secure form of server trust validation mitigating most, if not all, MITM attacks. +/// Applications are encouraged to always validate the host and require a valid certificate +/// chain in production environments. +/// +/// - disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid. +/// +/// - customEvaluation: Uses the associated closure to evaluate the validity of the server trust. +public enum ServerTrustPolicy { + case performDefaultEvaluation(validateHost: Bool) + case performRevokedEvaluation(validateHost: Bool, revocationFlags: CFOptionFlags) + case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool) + case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool) + case disableEvaluation + case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool) + + // MARK: - Bundle Location + + /// Returns all certificates within the given bundle with a `.cer` file extension. + /// + /// - parameter bundle: The bundle to search for all `.cer` files. + /// + /// - returns: All certificates within the given bundle. + public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] { + var certificates: [SecCertificate] = [] + + let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in + bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil) + }.joined()) + + for path in paths { + if + let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData, + let certificate = SecCertificateCreateWithData(nil, certificateData) + { + certificates.append(certificate) + } + } + + return certificates + } + + /// Returns all public keys within the given bundle with a `.cer` file extension. + /// + /// - parameter bundle: The bundle to search for all `*.cer` files. + /// + /// - returns: All public keys within the given bundle. + public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] { + var publicKeys: [SecKey] = [] + + for certificate in certificates(in: bundle) { + if let publicKey = publicKey(for: certificate) { + publicKeys.append(publicKey) + } + } + + return publicKeys + } + + // MARK: - Evaluation + + /// Evaluates whether the server trust is valid for the given host. + /// + /// - parameter serverTrust: The server trust to evaluate. + /// - parameter host: The host of the challenge protection space. + /// + /// - returns: Whether the server trust is valid. + public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool { + var serverTrustIsValid = false + + switch self { + case let .performDefaultEvaluation(validateHost): + let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + SecTrustSetPolicies(serverTrust, policy) + + serverTrustIsValid = trustIsValid(serverTrust) + case let .performRevokedEvaluation(validateHost, revocationFlags): + let defaultPolicy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + let revokedPolicy = SecPolicyCreateRevocation(revocationFlags) + SecTrustSetPolicies(serverTrust, [defaultPolicy, revokedPolicy] as CFTypeRef) + + serverTrustIsValid = trustIsValid(serverTrust) + case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost): + if validateCertificateChain { + let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + SecTrustSetPolicies(serverTrust, policy) + + SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray) + SecTrustSetAnchorCertificatesOnly(serverTrust, true) + + serverTrustIsValid = trustIsValid(serverTrust) + } else { + let serverCertificatesDataArray = certificateData(for: serverTrust) + let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates) + + outerLoop: for serverCertificateData in serverCertificatesDataArray { + for pinnedCertificateData in pinnedCertificatesDataArray { + if serverCertificateData == pinnedCertificateData { + serverTrustIsValid = true + break outerLoop + } + } + } + } + case let .pinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost): + var certificateChainEvaluationPassed = true + + if validateCertificateChain { + let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + SecTrustSetPolicies(serverTrust, policy) + + certificateChainEvaluationPassed = trustIsValid(serverTrust) + } + + if certificateChainEvaluationPassed { + outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: serverTrust) as [AnyObject] { + for pinnedPublicKey in pinnedPublicKeys as [AnyObject] { + if serverPublicKey.isEqual(pinnedPublicKey) { + serverTrustIsValid = true + break outerLoop + } + } + } + } + case .disableEvaluation: + serverTrustIsValid = true + case let .customEvaluation(closure): + serverTrustIsValid = closure(serverTrust, host) + } + + return serverTrustIsValid + } + + // MARK: - Private - Trust Validation + + private func trustIsValid(_ trust: SecTrust) -> Bool { + var isValid = false + + var result = SecTrustResultType.invalid + let status = SecTrustEvaluate(trust, &result) + + if status == errSecSuccess { + let unspecified = SecTrustResultType.unspecified + let proceed = SecTrustResultType.proceed + + + isValid = result == unspecified || result == proceed + } + + return isValid + } + + // MARK: - Private - Certificate Data + + private func certificateData(for trust: SecTrust) -> [Data] { + var certificates: [SecCertificate] = [] + + for index in 0.. [Data] { + return certificates.map { SecCertificateCopyData($0) as Data } + } + + // MARK: - Private - Public Key Extraction + + private static func publicKeys(for trust: SecTrust) -> [SecKey] { + var publicKeys: [SecKey] = [] + + for index in 0.. SecKey? { + var publicKey: SecKey? + + let policy = SecPolicyCreateBasicX509() + var trust: SecTrust? + let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) + + if let trust = trust, trustCreationStatus == errSecSuccess { + publicKey = SecTrustCopyPublicKey(trust) + } + + return publicKey + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/SessionDelegate.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/SessionDelegate.swift new file mode 100644 index 0000000..4964f1e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/SessionDelegate.swift @@ -0,0 +1,725 @@ +// +// SessionDelegate.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Responsible for handling all delegate callbacks for the underlying session. +open class SessionDelegate: NSObject { + + // MARK: URLSessionDelegate Overrides + + /// Overrides default behavior for URLSessionDelegate method `urlSession(_:didBecomeInvalidWithError:)`. + open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)? + + /// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`. + open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? + + /// Overrides all behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)` and requires the caller to call the `completionHandler`. + open var sessionDidReceiveChallengeWithCompletion: ((URLSession, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionDelegate method `urlSessionDidFinishEvents(forBackgroundURLSession:)`. + open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)? + + // MARK: URLSessionTaskDelegate Overrides + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`. + open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)? + + /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` and + /// requires the caller to call the `completionHandler`. + open var taskWillPerformHTTPRedirectionWithCompletion: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest, @escaping (URLRequest?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)`. + open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? + + /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)` and + /// requires the caller to call the `completionHandler`. + open var taskDidReceiveChallengeWithCompletion: ((URLSession, URLSessionTask, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)`. + open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)? + + /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)` and + /// requires the caller to call the `completionHandler`. + open var taskNeedNewBodyStreamWithCompletion: ((URLSession, URLSessionTask, @escaping (InputStream?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)`. + open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didCompleteWithError:)`. + open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)? + + // MARK: URLSessionDataDelegate Overrides + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)`. + open var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)? + + /// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)` and + /// requires caller to call the `completionHandler`. + open var dataTaskDidReceiveResponseWithCompletion: ((URLSession, URLSessionDataTask, URLResponse, @escaping (URLSession.ResponseDisposition) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didBecome:)`. + open var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)? + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:)`. + open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)? + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)`. + open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)? + + /// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)` and + /// requires caller to call the `completionHandler`. + open var dataTaskWillCacheResponseWithCompletion: ((URLSession, URLSessionDataTask, CachedURLResponse, @escaping (CachedURLResponse?) -> Void) -> Void)? + + // MARK: URLSessionDownloadDelegate Overrides + + /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didFinishDownloadingTo:)`. + open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)? + + /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`. + open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)? + + /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)`. + open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)? + + // MARK: URLSessionStreamDelegate Overrides + +#if !os(watchOS) + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:readClosedFor:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)? { + get { + return _streamTaskReadClosed as? (URLSession, URLSessionStreamTask) -> Void + } + set { + _streamTaskReadClosed = newValue + } + } + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:writeClosedFor:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskWriteClosed: ((URLSession, URLSessionStreamTask) -> Void)? { + get { + return _streamTaskWriteClosed as? (URLSession, URLSessionStreamTask) -> Void + } + set { + _streamTaskWriteClosed = newValue + } + } + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:betterRouteDiscoveredFor:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskBetterRouteDiscovered: ((URLSession, URLSessionStreamTask) -> Void)? { + get { + return _streamTaskBetterRouteDiscovered as? (URLSession, URLSessionStreamTask) -> Void + } + set { + _streamTaskBetterRouteDiscovered = newValue + } + } + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:streamTask:didBecome:outputStream:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskDidBecomeInputAndOutputStreams: ((URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void)? { + get { + return _streamTaskDidBecomeInputStream as? (URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void + } + set { + _streamTaskDidBecomeInputStream = newValue + } + } + + var _streamTaskReadClosed: Any? + var _streamTaskWriteClosed: Any? + var _streamTaskBetterRouteDiscovered: Any? + var _streamTaskDidBecomeInputStream: Any? + +#endif + + // MARK: Properties + + var retrier: RequestRetrier? + weak var sessionManager: SessionManager? + + var requests: [Int: Request] = [:] + private let lock = NSLock() + + /// Access the task delegate for the specified task in a thread-safe manner. + open subscript(task: URLSessionTask) -> Request? { + get { + lock.lock() ; defer { lock.unlock() } + return requests[task.taskIdentifier] + } + set { + lock.lock() ; defer { lock.unlock() } + requests[task.taskIdentifier] = newValue + } + } + + // MARK: Lifecycle + + /// Initializes the `SessionDelegate` instance. + /// + /// - returns: The new `SessionDelegate` instance. + public override init() { + super.init() + } + + // MARK: NSObject Overrides + + /// Returns a `Bool` indicating whether the `SessionDelegate` implements or inherits a method that can respond + /// to a specified message. + /// + /// - parameter selector: A selector that identifies a message. + /// + /// - returns: `true` if the receiver implements or inherits a method that can respond to selector, otherwise `false`. + open override func responds(to selector: Selector) -> Bool { + #if !os(macOS) + if selector == #selector(URLSessionDelegate.urlSessionDidFinishEvents(forBackgroundURLSession:)) { + return sessionDidFinishEventsForBackgroundURLSession != nil + } + #endif + + #if !os(watchOS) + if #available(iOS 9.0, macOS 10.11, tvOS 9.0, *) { + switch selector { + case #selector(URLSessionStreamDelegate.urlSession(_:readClosedFor:)): + return streamTaskReadClosed != nil + case #selector(URLSessionStreamDelegate.urlSession(_:writeClosedFor:)): + return streamTaskWriteClosed != nil + case #selector(URLSessionStreamDelegate.urlSession(_:betterRouteDiscoveredFor:)): + return streamTaskBetterRouteDiscovered != nil + case #selector(URLSessionStreamDelegate.urlSession(_:streamTask:didBecome:outputStream:)): + return streamTaskDidBecomeInputAndOutputStreams != nil + default: + break + } + } + #endif + + switch selector { + case #selector(URLSessionDelegate.urlSession(_:didBecomeInvalidWithError:)): + return sessionDidBecomeInvalidWithError != nil + case #selector(URLSessionDelegate.urlSession(_:didReceive:completionHandler:)): + return (sessionDidReceiveChallenge != nil || sessionDidReceiveChallengeWithCompletion != nil) + case #selector(URLSessionTaskDelegate.urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)): + return (taskWillPerformHTTPRedirection != nil || taskWillPerformHTTPRedirectionWithCompletion != nil) + case #selector(URLSessionDataDelegate.urlSession(_:dataTask:didReceive:completionHandler:)): + return (dataTaskDidReceiveResponse != nil || dataTaskDidReceiveResponseWithCompletion != nil) + default: + return type(of: self).instancesRespond(to: selector) + } + } +} + +// MARK: - URLSessionDelegate + +extension SessionDelegate: URLSessionDelegate { + /// Tells the delegate that the session has been invalidated. + /// + /// - parameter session: The session object that was invalidated. + /// - parameter error: The error that caused invalidation, or nil if the invalidation was explicit. + open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) { + sessionDidBecomeInvalidWithError?(session, error) + } + + /// Requests credentials from the delegate in response to a session-level authentication request from the + /// remote server. + /// + /// - parameter session: The session containing the task that requested authentication. + /// - parameter challenge: An object that contains the request for authentication. + /// - parameter completionHandler: A handler that your delegate method must call providing the disposition + /// and credential. + open func urlSession( + _ session: URLSession, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + { + guard sessionDidReceiveChallengeWithCompletion == nil else { + sessionDidReceiveChallengeWithCompletion?(session, challenge, completionHandler) + return + } + + var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling + var credential: URLCredential? + + if let sessionDidReceiveChallenge = sessionDidReceiveChallenge { + (disposition, credential) = sessionDidReceiveChallenge(session, challenge) + } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { + let host = challenge.protectionSpace.host + + if + let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host), + let serverTrust = challenge.protectionSpace.serverTrust + { + if serverTrustPolicy.evaluate(serverTrust, forHost: host) { + disposition = .useCredential + credential = URLCredential(trust: serverTrust) + } else { + disposition = .cancelAuthenticationChallenge + } + } + } + + completionHandler(disposition, credential) + } + +#if !os(macOS) + + /// Tells the delegate that all messages enqueued for a session have been delivered. + /// + /// - parameter session: The session that no longer has any outstanding requests. + open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { + sessionDidFinishEventsForBackgroundURLSession?(session) + } + +#endif +} + +// MARK: - URLSessionTaskDelegate + +extension SessionDelegate: URLSessionTaskDelegate { + /// Tells the delegate that the remote server requested an HTTP redirect. + /// + /// - parameter session: The session containing the task whose request resulted in a redirect. + /// - parameter task: The task whose request resulted in a redirect. + /// - parameter response: An object containing the server’s response to the original request. + /// - parameter request: A URL request object filled out with the new location. + /// - parameter completionHandler: A closure that your handler should call with either the value of the request + /// parameter, a modified URL request object, or NULL to refuse the redirect and + /// return the body of the redirect response. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + guard taskWillPerformHTTPRedirectionWithCompletion == nil else { + taskWillPerformHTTPRedirectionWithCompletion?(session, task, response, request, completionHandler) + return + } + + var redirectRequest: URLRequest? = request + + if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection { + redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request) + } + + completionHandler(redirectRequest) + } + + /// Requests credentials from the delegate in response to an authentication request from the remote server. + /// + /// - parameter session: The session containing the task whose request requires authentication. + /// - parameter task: The task whose request requires authentication. + /// - parameter challenge: An object that contains the request for authentication. + /// - parameter completionHandler: A handler that your delegate method must call providing the disposition + /// and credential. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + { + guard taskDidReceiveChallengeWithCompletion == nil else { + taskDidReceiveChallengeWithCompletion?(session, task, challenge, completionHandler) + return + } + + if let taskDidReceiveChallenge = taskDidReceiveChallenge { + let result = taskDidReceiveChallenge(session, task, challenge) + completionHandler(result.0, result.1) + } else if let delegate = self[task]?.delegate { + delegate.urlSession( + session, + task: task, + didReceive: challenge, + completionHandler: completionHandler + ) + } else { + urlSession(session, didReceive: challenge, completionHandler: completionHandler) + } + } + + /// Tells the delegate when a task requires a new request body stream to send to the remote server. + /// + /// - parameter session: The session containing the task that needs a new body stream. + /// - parameter task: The task that needs a new body stream. + /// - parameter completionHandler: A completion handler that your delegate method should call with the new body stream. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) + { + guard taskNeedNewBodyStreamWithCompletion == nil else { + taskNeedNewBodyStreamWithCompletion?(session, task, completionHandler) + return + } + + if let taskNeedNewBodyStream = taskNeedNewBodyStream { + completionHandler(taskNeedNewBodyStream(session, task)) + } else if let delegate = self[task]?.delegate { + delegate.urlSession(session, task: task, needNewBodyStream: completionHandler) + } + } + + /// Periodically informs the delegate of the progress of sending body content to the server. + /// + /// - parameter session: The session containing the data task. + /// - parameter task: The data task. + /// - parameter bytesSent: The number of bytes sent since the last time this delegate method was called. + /// - parameter totalBytesSent: The total number of bytes sent so far. + /// - parameter totalBytesExpectedToSend: The expected length of the body data. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + didSendBodyData bytesSent: Int64, + totalBytesSent: Int64, + totalBytesExpectedToSend: Int64) + { + if let taskDidSendBodyData = taskDidSendBodyData { + taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) + } else if let delegate = self[task]?.delegate as? UploadTaskDelegate { + delegate.URLSession( + session, + task: task, + didSendBodyData: bytesSent, + totalBytesSent: totalBytesSent, + totalBytesExpectedToSend: totalBytesExpectedToSend + ) + } + } + +#if !os(watchOS) + + /// Tells the delegate that the session finished collecting metrics for the task. + /// + /// - parameter session: The session collecting the metrics. + /// - parameter task: The task whose metrics have been collected. + /// - parameter metrics: The collected metrics. + @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) + @objc(URLSession:task:didFinishCollectingMetrics:) + open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { + self[task]?.delegate.metrics = metrics + } + +#endif + + /// Tells the delegate that the task finished transferring data. + /// + /// - parameter session: The session containing the task whose request finished transferring data. + /// - parameter task: The task whose request finished transferring data. + /// - parameter error: If an error occurred, an error object indicating how the transfer failed, otherwise nil. + open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + /// Executed after it is determined that the request is not going to be retried + let completeTask: (URLSession, URLSessionTask, Error?) -> Void = { [weak self] session, task, error in + guard let strongSelf = self else { return } + + strongSelf.taskDidComplete?(session, task, error) + + strongSelf[task]?.delegate.urlSession(session, task: task, didCompleteWithError: error) + + var userInfo: [String: Any] = [Notification.Key.Task: task] + + if let data = (strongSelf[task]?.delegate as? DataTaskDelegate)?.data { + userInfo[Notification.Key.ResponseData] = data + } + + NotificationCenter.default.post( + name: Notification.Name.Task.DidComplete, + object: strongSelf, + userInfo: userInfo + ) + + strongSelf[task] = nil + } + + guard let request = self[task], let sessionManager = sessionManager else { + completeTask(session, task, error) + return + } + + // Run all validations on the request before checking if an error occurred + request.validations.forEach { $0() } + + // Determine whether an error has occurred + var error: Error? = error + + if request.delegate.error != nil { + error = request.delegate.error + } + + /// If an error occurred and the retrier is set, asynchronously ask the retrier if the request + /// should be retried. Otherwise, complete the task by notifying the task delegate. + if let retrier = retrier, let error = error { + retrier.should(sessionManager, retry: request, with: error) { [weak self] shouldRetry, timeDelay in + guard shouldRetry else { completeTask(session, task, error) ; return } + + DispatchQueue.utility.after(timeDelay) { [weak self] in + guard let strongSelf = self else { return } + + let retrySucceeded = strongSelf.sessionManager?.retry(request) ?? false + + if retrySucceeded, let task = request.task { + strongSelf[task] = request + return + } else { + completeTask(session, task, error) + } + } + } + } else { + completeTask(session, task, error) + } + } +} + +// MARK: - URLSessionDataDelegate + +extension SessionDelegate: URLSessionDataDelegate { + /// Tells the delegate that the data task received the initial reply (headers) from the server. + /// + /// - parameter session: The session containing the data task that received an initial reply. + /// - parameter dataTask: The data task that received an initial reply. + /// - parameter response: A URL response object populated with headers. + /// - parameter completionHandler: A completion handler that your code calls to continue the transfer, passing a + /// constant to indicate whether the transfer should continue as a data task or + /// should become a download task. + open func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didReceive response: URLResponse, + completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) + { + guard dataTaskDidReceiveResponseWithCompletion == nil else { + dataTaskDidReceiveResponseWithCompletion?(session, dataTask, response, completionHandler) + return + } + + var disposition: URLSession.ResponseDisposition = .allow + + if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse { + disposition = dataTaskDidReceiveResponse(session, dataTask, response) + } + + completionHandler(disposition) + } + + /// Tells the delegate that the data task was changed to a download task. + /// + /// - parameter session: The session containing the task that was replaced by a download task. + /// - parameter dataTask: The data task that was replaced by a download task. + /// - parameter downloadTask: The new download task that replaced the data task. + open func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didBecome downloadTask: URLSessionDownloadTask) + { + if let dataTaskDidBecomeDownloadTask = dataTaskDidBecomeDownloadTask { + dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask) + } else { + self[downloadTask]?.delegate = DownloadTaskDelegate(task: downloadTask) + } + } + + /// Tells the delegate that the data task has received some of the expected data. + /// + /// - parameter session: The session containing the data task that provided data. + /// - parameter dataTask: The data task that provided data. + /// - parameter data: A data object containing the transferred data. + open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + if let dataTaskDidReceiveData = dataTaskDidReceiveData { + dataTaskDidReceiveData(session, dataTask, data) + } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate { + delegate.urlSession(session, dataTask: dataTask, didReceive: data) + } + } + + /// Asks the delegate whether the data (or upload) task should store the response in the cache. + /// + /// - parameter session: The session containing the data (or upload) task. + /// - parameter dataTask: The data (or upload) task. + /// - parameter proposedResponse: The default caching behavior. This behavior is determined based on the current + /// caching policy and the values of certain received headers, such as the Pragma + /// and Cache-Control headers. + /// - parameter completionHandler: A block that your handler must call, providing either the original proposed + /// response, a modified version of that response, or NULL to prevent caching the + /// response. If your delegate implements this method, it must call this completion + /// handler; otherwise, your app leaks memory. + open func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + willCacheResponse proposedResponse: CachedURLResponse, + completionHandler: @escaping (CachedURLResponse?) -> Void) + { + guard dataTaskWillCacheResponseWithCompletion == nil else { + dataTaskWillCacheResponseWithCompletion?(session, dataTask, proposedResponse, completionHandler) + return + } + + if let dataTaskWillCacheResponse = dataTaskWillCacheResponse { + completionHandler(dataTaskWillCacheResponse(session, dataTask, proposedResponse)) + } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate { + delegate.urlSession( + session, + dataTask: dataTask, + willCacheResponse: proposedResponse, + completionHandler: completionHandler + ) + } else { + completionHandler(proposedResponse) + } + } +} + +// MARK: - URLSessionDownloadDelegate + +extension SessionDelegate: URLSessionDownloadDelegate { + /// Tells the delegate that a download task has finished downloading. + /// + /// - parameter session: The session containing the download task that finished. + /// - parameter downloadTask: The download task that finished. + /// - parameter location: A file URL for the temporary file. Because the file is temporary, you must either + /// open the file for reading or move it to a permanent location in your app’s sandbox + /// container directory before returning from this delegate method. + open func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didFinishDownloadingTo location: URL) + { + if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL { + downloadTaskDidFinishDownloadingToURL(session, downloadTask, location) + } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate { + delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location) + } + } + + /// Periodically informs the delegate about the download’s progress. + /// + /// - parameter session: The session containing the download task. + /// - parameter downloadTask: The download task. + /// - parameter bytesWritten: The number of bytes transferred since the last time this delegate + /// method was called. + /// - parameter totalBytesWritten: The total number of bytes transferred so far. + /// - parameter totalBytesExpectedToWrite: The expected length of the file, as provided by the Content-Length + /// header. If this header was not provided, the value is + /// `NSURLSessionTransferSizeUnknown`. + open func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didWriteData bytesWritten: Int64, + totalBytesWritten: Int64, + totalBytesExpectedToWrite: Int64) + { + if let downloadTaskDidWriteData = downloadTaskDidWriteData { + downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) + } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate { + delegate.urlSession( + session, + downloadTask: downloadTask, + didWriteData: bytesWritten, + totalBytesWritten: totalBytesWritten, + totalBytesExpectedToWrite: totalBytesExpectedToWrite + ) + } + } + + /// Tells the delegate that the download task has resumed downloading. + /// + /// - parameter session: The session containing the download task that finished. + /// - parameter downloadTask: The download task that resumed. See explanation in the discussion. + /// - parameter fileOffset: If the file's cache policy or last modified date prevents reuse of the + /// existing content, then this value is zero. Otherwise, this value is an + /// integer representing the number of bytes on disk that do not need to be + /// retrieved again. + /// - parameter expectedTotalBytes: The expected length of the file, as provided by the Content-Length header. + /// If this header was not provided, the value is NSURLSessionTransferSizeUnknown. + open func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didResumeAtOffset fileOffset: Int64, + expectedTotalBytes: Int64) + { + if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { + downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) + } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate { + delegate.urlSession( + session, + downloadTask: downloadTask, + didResumeAtOffset: fileOffset, + expectedTotalBytes: expectedTotalBytes + ) + } + } +} + +// MARK: - URLSessionStreamDelegate + +#if !os(watchOS) + +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +extension SessionDelegate: URLSessionStreamDelegate { + /// Tells the delegate that the read side of the connection has been closed. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + open func urlSession(_ session: URLSession, readClosedFor streamTask: URLSessionStreamTask) { + streamTaskReadClosed?(session, streamTask) + } + + /// Tells the delegate that the write side of the connection has been closed. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + open func urlSession(_ session: URLSession, writeClosedFor streamTask: URLSessionStreamTask) { + streamTaskWriteClosed?(session, streamTask) + } + + /// Tells the delegate that the system has determined that a better route to the host is available. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + open func urlSession(_ session: URLSession, betterRouteDiscoveredFor streamTask: URLSessionStreamTask) { + streamTaskBetterRouteDiscovered?(session, streamTask) + } + + /// Tells the delegate that the stream task has been completed and provides the unopened stream objects. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + /// - parameter inputStream: The new input stream. + /// - parameter outputStream: The new output stream. + open func urlSession( + _ session: URLSession, + streamTask: URLSessionStreamTask, + didBecome inputStream: InputStream, + outputStream: OutputStream) + { + streamTaskDidBecomeInputAndOutputStreams?(session, streamTask, inputStream, outputStream) + } +} + +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/SessionManager.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/SessionManager.swift new file mode 100644 index 0000000..02c36a7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/SessionManager.swift @@ -0,0 +1,899 @@ +// +// SessionManager.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Responsible for creating and managing `Request` objects, as well as their underlying `NSURLSession`. +open class SessionManager { + + // MARK: - Helper Types + + /// Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as + /// associated values. + /// + /// - Success: Represents a successful `MultipartFormData` encoding and contains the new `UploadRequest` along with + /// streaming information. + /// - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding + /// error. + public enum MultipartFormDataEncodingResult { + case success(request: UploadRequest, streamingFromDisk: Bool, streamFileURL: URL?) + case failure(Error) + } + + // MARK: - Properties + + /// A default instance of `SessionManager`, used by top-level Alamofire request methods, and suitable for use + /// directly for any ad hoc requests. + public static let `default`: SessionManager = { + let configuration = URLSessionConfiguration.default + configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders + + return SessionManager(configuration: configuration) + }() + + /// Creates default values for the "Accept-Encoding", "Accept-Language" and "User-Agent" headers. + public static let defaultHTTPHeaders: HTTPHeaders = { + // Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3 + let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5" + + // Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5 + let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in + let quality = 1.0 - (Double(index) * 0.1) + return "\(languageCode);q=\(quality)" + }.joined(separator: ", ") + + // User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3 + // Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0` + let userAgent: String = { + if let info = Bundle.main.infoDictionary { + let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown" + let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown" + let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown" + let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown" + + let osNameVersion: String = { + let version = ProcessInfo.processInfo.operatingSystemVersion + let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)" + + let osName: String = { + #if os(iOS) + return "iOS" + #elseif os(watchOS) + return "watchOS" + #elseif os(tvOS) + return "tvOS" + #elseif os(macOS) + return "OS X" + #elseif os(Linux) + return "Linux" + #else + return "Unknown" + #endif + }() + + return "\(osName) \(versionString)" + }() + + let alamofireVersion: String = { + guard + let afInfo = Bundle(for: SessionManager.self).infoDictionary, + let build = afInfo["CFBundleShortVersionString"] + else { return "Unknown" } + + return "Alamofire/\(build)" + }() + + return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)" + } + + return "Alamofire" + }() + + return [ + "Accept-Encoding": acceptEncoding, + "Accept-Language": acceptLanguage, + "User-Agent": userAgent + ] + }() + + /// Default memory threshold used when encoding `MultipartFormData` in bytes. + public static let multipartFormDataEncodingMemoryThreshold: UInt64 = 10_000_000 + + /// The underlying session. + public let session: URLSession + + /// The session delegate handling all the task and session delegate callbacks. + public let delegate: SessionDelegate + + /// Whether to start requests immediately after being constructed. `true` by default. + open var startRequestsImmediately: Bool = true + + /// The request adapter called each time a new request is created. + open var adapter: RequestAdapter? + + /// The request retrier called each time a request encounters an error to determine whether to retry the request. + open var retrier: RequestRetrier? { + get { return delegate.retrier } + set { delegate.retrier = newValue } + } + + /// The background completion handler closure provided by the UIApplicationDelegate + /// `application:handleEventsForBackgroundURLSession:completionHandler:` method. By setting the background + /// completion handler, the SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` closure implementation + /// will automatically call the handler. + /// + /// If you need to handle your own events before the handler is called, then you need to override the + /// SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` and manually call the handler when finished. + /// + /// `nil` by default. + open var backgroundCompletionHandler: (() -> Void)? + + let queue = DispatchQueue(label: "org.alamofire.session-manager." + UUID().uuidString) + + // MARK: - Lifecycle + + /// Creates an instance with the specified `configuration`, `delegate` and `serverTrustPolicyManager`. + /// + /// - parameter configuration: The configuration used to construct the managed session. + /// `URLSessionConfiguration.default` by default. + /// - parameter delegate: The delegate used when initializing the session. `SessionDelegate()` by + /// default. + /// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust + /// challenges. `nil` by default. + /// + /// - returns: The new `SessionManager` instance. + public init( + configuration: URLSessionConfiguration = URLSessionConfiguration.default, + delegate: SessionDelegate = SessionDelegate(), + serverTrustPolicyManager: ServerTrustPolicyManager? = nil) + { + self.delegate = delegate + self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil) + + commonInit(serverTrustPolicyManager: serverTrustPolicyManager) + } + + /// Creates an instance with the specified `session`, `delegate` and `serverTrustPolicyManager`. + /// + /// - parameter session: The URL session. + /// - parameter delegate: The delegate of the URL session. Must equal the URL session's delegate. + /// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust + /// challenges. `nil` by default. + /// + /// - returns: The new `SessionManager` instance if the URL session's delegate matches; `nil` otherwise. + public init?( + session: URLSession, + delegate: SessionDelegate, + serverTrustPolicyManager: ServerTrustPolicyManager? = nil) + { + guard delegate === session.delegate else { return nil } + + self.delegate = delegate + self.session = session + + commonInit(serverTrustPolicyManager: serverTrustPolicyManager) + } + + private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?) { + session.serverTrustPolicyManager = serverTrustPolicyManager + + delegate.sessionManager = self + + delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in + guard let strongSelf = self else { return } + DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() } + } + } + + deinit { + session.invalidateAndCancel() + } + + // MARK: - Data Request + + /// Creates a `DataRequest` to retrieve the contents of the specified `url`, `method`, `parameters`, `encoding` + /// and `headers`. + /// + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.get` by default. + /// - parameter parameters: The parameters. `nil` by default. + /// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `DataRequest`. + @discardableResult + open func request( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil) + -> DataRequest + { + var originalRequest: URLRequest? + + do { + originalRequest = try URLRequest(url: url, method: method, headers: headers) + let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters) + return request(encodedURLRequest) + } catch { + return request(originalRequest, failedWith: error) + } + } + + /// Creates a `DataRequest` to retrieve the contents of a URL based on the specified `urlRequest`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `DataRequest`. + @discardableResult + open func request(_ urlRequest: URLRequestConvertible) -> DataRequest { + var originalRequest: URLRequest? + + do { + originalRequest = try urlRequest.asURLRequest() + let originalTask = DataRequest.Requestable(urlRequest: originalRequest!) + + let task = try originalTask.task(session: session, adapter: adapter, queue: queue) + let request = DataRequest(session: session, requestTask: .data(originalTask, task)) + + delegate[task] = request + + if startRequestsImmediately { request.resume() } + + return request + } catch { + return request(originalRequest, failedWith: error) + } + } + + // MARK: Private - Request Implementation + + private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest { + var requestTask: Request.RequestTask = .data(nil, nil) + + if let urlRequest = urlRequest { + let originalTask = DataRequest.Requestable(urlRequest: urlRequest) + requestTask = .data(originalTask, nil) + } + + let underlyingError = error.underlyingAdaptError ?? error + let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError) + + if let retrier = retrier, error is AdaptError { + allowRetrier(retrier, toRetry: request, with: underlyingError) + } else { + if startRequestsImmediately { request.resume() } + } + + return request + } + + // MARK: - Download Request + + // MARK: URL Request + + /// Creates a `DownloadRequest` to retrieve the contents the specified `url`, `method`, `parameters`, `encoding`, + /// `headers` and save them to the `destination`. + /// + /// If `destination` is not specified, the contents will remain in the temporary location determined by the + /// underlying URL session. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.get` by default. + /// - parameter parameters: The parameters. `nil` by default. + /// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. + /// + /// - returns: The created `DownloadRequest`. + @discardableResult + open func download( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + let encodedURLRequest = try encoding.encode(urlRequest, with: parameters) + return download(encodedURLRequest, to: destination) + } catch { + return download(nil, to: destination, failedWith: error) + } + } + + /// Creates a `DownloadRequest` to retrieve the contents of a URL based on the specified `urlRequest` and save + /// them to the `destination`. + /// + /// If `destination` is not specified, the contents will remain in the temporary location determined by the + /// underlying URL session. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter urlRequest: The URL request + /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. + /// + /// - returns: The created `DownloadRequest`. + @discardableResult + open func download( + _ urlRequest: URLRequestConvertible, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest + { + do { + let urlRequest = try urlRequest.asURLRequest() + return download(.request(urlRequest), to: destination) + } catch { + return download(nil, to: destination, failedWith: error) + } + } + + // MARK: Resume Data + + /// Creates a `DownloadRequest` from the `resumeData` produced from a previous request cancellation to retrieve + /// the contents of the original request and save them to the `destination`. + /// + /// If `destination` is not specified, the contents will remain in the temporary location determined by the + /// underlying URL session. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken + /// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the + /// data is written incorrectly and will always fail to resume the download. For more information about the bug and + /// possible workarounds, please refer to the following Stack Overflow post: + /// + /// - http://stackoverflow.com/a/39347461/1342462 + /// + /// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask` + /// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for + /// additional information. + /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. + /// + /// - returns: The created `DownloadRequest`. + @discardableResult + open func download( + resumingWith resumeData: Data, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest + { + return download(.resumeData(resumeData), to: destination) + } + + // MARK: Private - Download Implementation + + private func download( + _ downloadable: DownloadRequest.Downloadable, + to destination: DownloadRequest.DownloadFileDestination?) + -> DownloadRequest + { + do { + let task = try downloadable.task(session: session, adapter: adapter, queue: queue) + let download = DownloadRequest(session: session, requestTask: .download(downloadable, task)) + + download.downloadDelegate.destination = destination + + delegate[task] = download + + if startRequestsImmediately { download.resume() } + + return download + } catch { + return download(downloadable, to: destination, failedWith: error) + } + } + + private func download( + _ downloadable: DownloadRequest.Downloadable?, + to destination: DownloadRequest.DownloadFileDestination?, + failedWith error: Error) + -> DownloadRequest + { + var downloadTask: Request.RequestTask = .download(nil, nil) + + if let downloadable = downloadable { + downloadTask = .download(downloadable, nil) + } + + let underlyingError = error.underlyingAdaptError ?? error + + let download = DownloadRequest(session: session, requestTask: downloadTask, error: underlyingError) + download.downloadDelegate.destination = destination + + if let retrier = retrier, error is AdaptError { + allowRetrier(retrier, toRetry: download, with: underlyingError) + } else { + if startRequestsImmediately { download.resume() } + } + + return download + } + + // MARK: - Upload Request + + // MARK: File + + /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `file`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter file: The file to upload. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload( + _ fileURL: URL, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + return upload(fileURL, with: urlRequest) + } catch { + return upload(nil, failedWith: error) + } + } + + /// Creates a `UploadRequest` from the specified `urlRequest` for uploading the `file`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter file: The file to upload. + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest { + do { + let urlRequest = try urlRequest.asURLRequest() + return upload(.file(fileURL, urlRequest)) + } catch { + return upload(nil, failedWith: error) + } + } + + // MARK: Data + + /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `data`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter data: The data to upload. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload( + _ data: Data, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + return upload(data, with: urlRequest) + } catch { + return upload(nil, failedWith: error) + } + } + + /// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `data`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter data: The data to upload. + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest { + do { + let urlRequest = try urlRequest.asURLRequest() + return upload(.data(data, urlRequest)) + } catch { + return upload(nil, failedWith: error) + } + } + + // MARK: InputStream + + /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `stream`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter stream: The stream to upload. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload( + _ stream: InputStream, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + return upload(stream, with: urlRequest) + } catch { + return upload(nil, failedWith: error) + } + } + + /// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `stream`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter stream: The stream to upload. + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest { + do { + let urlRequest = try urlRequest.asURLRequest() + return upload(.stream(stream, urlRequest)) + } catch { + return upload(nil, failedWith: error) + } + } + + // MARK: MultipartFormData + + /// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new + /// `UploadRequest` using the `url`, `method` and `headers`. + /// + /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative + /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most + /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to + /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory + /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be + /// used for larger payloads such as video content. + /// + /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory + /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, + /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk + /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding + /// technique was used. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. + /// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. + /// `multipartFormDataEncodingMemoryThreshold` by default. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. + open func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil, + queue: DispatchQueue? = nil, + encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?) + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + + return upload( + multipartFormData: multipartFormData, + usingThreshold: encodingMemoryThreshold, + with: urlRequest, + queue: queue, + encodingCompletion: encodingCompletion + ) + } catch { + (queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) } + } + } + + /// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new + /// `UploadRequest` using the `urlRequest`. + /// + /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative + /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most + /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to + /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory + /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be + /// used for larger payloads such as video content. + /// + /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory + /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, + /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk + /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding + /// technique was used. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. + /// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. + /// `multipartFormDataEncodingMemoryThreshold` by default. + /// - parameter urlRequest: The URL request. + /// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. + open func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + with urlRequest: URLRequestConvertible, + queue: DispatchQueue? = nil, + encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?) + { + DispatchQueue.global(qos: .utility).async { + let formData = MultipartFormData() + multipartFormData(formData) + + var tempFileURL: URL? + + do { + var urlRequestWithContentType = try urlRequest.asURLRequest() + urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type") + + let isBackgroundSession = self.session.configuration.identifier != nil + + if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession { + let data = try formData.encode() + + let encodingResult = MultipartFormDataEncodingResult.success( + request: self.upload(data, with: urlRequestWithContentType), + streamingFromDisk: false, + streamFileURL: nil + ) + + (queue ?? DispatchQueue.main).async { encodingCompletion?(encodingResult) } + } else { + let fileManager = FileManager.default + let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory()) + let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data") + let fileName = UUID().uuidString + let fileURL = directoryURL.appendingPathComponent(fileName) + + tempFileURL = fileURL + + var directoryError: Error? + + // Create directory inside serial queue to ensure two threads don't do this in parallel + self.queue.sync { + do { + try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil) + } catch { + directoryError = error + } + } + + if let directoryError = directoryError { throw directoryError } + + try formData.writeEncodedData(to: fileURL) + + let upload = self.upload(fileURL, with: urlRequestWithContentType) + + // Cleanup the temp file once the upload is complete + upload.delegate.queue.addOperation { + do { + try FileManager.default.removeItem(at: fileURL) + } catch { + // No-op + } + } + + (queue ?? DispatchQueue.main).async { + let encodingResult = MultipartFormDataEncodingResult.success( + request: upload, + streamingFromDisk: true, + streamFileURL: fileURL + ) + + encodingCompletion?(encodingResult) + } + } + } catch { + // Cleanup the temp file in the event that the multipart form data encoding failed + if let tempFileURL = tempFileURL { + do { + try FileManager.default.removeItem(at: tempFileURL) + } catch { + // No-op + } + } + + (queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) } + } + } + } + + // MARK: Private - Upload Implementation + + private func upload(_ uploadable: UploadRequest.Uploadable) -> UploadRequest { + do { + let task = try uploadable.task(session: session, adapter: adapter, queue: queue) + let upload = UploadRequest(session: session, requestTask: .upload(uploadable, task)) + + if case let .stream(inputStream, _) = uploadable { + upload.delegate.taskNeedNewBodyStream = { _, _ in inputStream } + } + + delegate[task] = upload + + if startRequestsImmediately { upload.resume() } + + return upload + } catch { + return upload(uploadable, failedWith: error) + } + } + + private func upload(_ uploadable: UploadRequest.Uploadable?, failedWith error: Error) -> UploadRequest { + var uploadTask: Request.RequestTask = .upload(nil, nil) + + if let uploadable = uploadable { + uploadTask = .upload(uploadable, nil) + } + + let underlyingError = error.underlyingAdaptError ?? error + let upload = UploadRequest(session: session, requestTask: uploadTask, error: underlyingError) + + if let retrier = retrier, error is AdaptError { + allowRetrier(retrier, toRetry: upload, with: underlyingError) + } else { + if startRequestsImmediately { upload.resume() } + } + + return upload + } + +#if !os(watchOS) + + // MARK: - Stream Request + + // MARK: Hostname and Port + + /// Creates a `StreamRequest` for bidirectional streaming using the `hostname` and `port`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter hostName: The hostname of the server to connect to. + /// - parameter port: The port of the server to connect to. + /// + /// - returns: The created `StreamRequest`. + @discardableResult + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open func stream(withHostName hostName: String, port: Int) -> StreamRequest { + return stream(.stream(hostName: hostName, port: port)) + } + + // MARK: NetService + + /// Creates a `StreamRequest` for bidirectional streaming using the `netService`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter netService: The net service used to identify the endpoint. + /// + /// - returns: The created `StreamRequest`. + @discardableResult + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open func stream(with netService: NetService) -> StreamRequest { + return stream(.netService(netService)) + } + + // MARK: Private - Stream Implementation + + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + private func stream(_ streamable: StreamRequest.Streamable) -> StreamRequest { + do { + let task = try streamable.task(session: session, adapter: adapter, queue: queue) + let request = StreamRequest(session: session, requestTask: .stream(streamable, task)) + + delegate[task] = request + + if startRequestsImmediately { request.resume() } + + return request + } catch { + return stream(failedWith: error) + } + } + + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + private func stream(failedWith error: Error) -> StreamRequest { + let stream = StreamRequest(session: session, requestTask: .stream(nil, nil), error: error) + if startRequestsImmediately { stream.resume() } + return stream + } + +#endif + + // MARK: - Internal - Retry Request + + func retry(_ request: Request) -> Bool { + guard let originalTask = request.originalTask else { return false } + + do { + let task = try originalTask.task(session: session, adapter: adapter, queue: queue) + + if let originalTask = request.task { + delegate[originalTask] = nil // removes the old request to avoid endless growth + } + + request.delegate.task = task // resets all task delegate data + + request.retryCount += 1 + request.startTime = CFAbsoluteTimeGetCurrent() + request.endTime = nil + + task.resume() + + return true + } catch { + request.delegate.error = error.underlyingAdaptError ?? error + return false + } + } + + private func allowRetrier(_ retrier: RequestRetrier, toRetry request: Request, with error: Error) { + DispatchQueue.utility.async { [weak self] in + guard let strongSelf = self else { return } + + retrier.should(strongSelf, retry: request, with: error) { shouldRetry, timeDelay in + guard let strongSelf = self else { return } + + guard shouldRetry else { + if strongSelf.startRequestsImmediately { request.resume() } + return + } + + DispatchQueue.utility.after(timeDelay) { + guard let strongSelf = self else { return } + + let retrySucceeded = strongSelf.retry(request) + + if retrySucceeded, let task = request.task { + strongSelf.delegate[task] = request + } else { + if strongSelf.startRequestsImmediately { request.resume() } + } + } + } + } + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/TaskDelegate.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/TaskDelegate.swift new file mode 100644 index 0000000..5705737 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/TaskDelegate.swift @@ -0,0 +1,466 @@ +// +// TaskDelegate.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// The task delegate is responsible for handling all delegate callbacks for the underlying task as well as +/// executing all operations attached to the serial operation queue upon task completion. +open class TaskDelegate: NSObject { + + // MARK: Properties + + /// The serial operation queue used to execute all operations after the task completes. + public let queue: OperationQueue + + /// The data returned by the server. + public var data: Data? { return nil } + + /// The error generated throughout the lifecyle of the task. + public var error: Error? + + var task: URLSessionTask? { + set { + taskLock.lock(); defer { taskLock.unlock() } + _task = newValue + } + get { + taskLock.lock(); defer { taskLock.unlock() } + return _task + } + } + + var initialResponseTime: CFAbsoluteTime? + var credential: URLCredential? + var metrics: AnyObject? // URLSessionTaskMetrics + + private var _task: URLSessionTask? { + didSet { reset() } + } + + private let taskLock = NSLock() + + // MARK: Lifecycle + + init(task: URLSessionTask?) { + _task = task + + self.queue = { + let operationQueue = OperationQueue() + + operationQueue.maxConcurrentOperationCount = 1 + operationQueue.isSuspended = true + operationQueue.qualityOfService = .utility + + return operationQueue + }() + } + + func reset() { + error = nil + initialResponseTime = nil + } + + // MARK: URLSessionTaskDelegate + + var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)? + var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? + var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)? + var taskDidCompleteWithError: ((URLSession, URLSessionTask, Error?) -> Void)? + + @objc(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:) + func urlSession( + _ session: URLSession, + task: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + var redirectRequest: URLRequest? = request + + if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection { + redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request) + } + + completionHandler(redirectRequest) + } + + @objc(URLSession:task:didReceiveChallenge:completionHandler:) + func urlSession( + _ session: URLSession, + task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + { + var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling + var credential: URLCredential? + + if let taskDidReceiveChallenge = taskDidReceiveChallenge { + (disposition, credential) = taskDidReceiveChallenge(session, task, challenge) + } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { + let host = challenge.protectionSpace.host + + if + let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host), + let serverTrust = challenge.protectionSpace.serverTrust + { + if serverTrustPolicy.evaluate(serverTrust, forHost: host) { + disposition = .useCredential + credential = URLCredential(trust: serverTrust) + } else { + disposition = .cancelAuthenticationChallenge + } + } + } else { + if challenge.previousFailureCount > 0 { + disposition = .rejectProtectionSpace + } else { + credential = self.credential ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace) + + if credential != nil { + disposition = .useCredential + } + } + } + + completionHandler(disposition, credential) + } + + @objc(URLSession:task:needNewBodyStream:) + func urlSession( + _ session: URLSession, + task: URLSessionTask, + needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) + { + var bodyStream: InputStream? + + if let taskNeedNewBodyStream = taskNeedNewBodyStream { + bodyStream = taskNeedNewBodyStream(session, task) + } + + completionHandler(bodyStream) + } + + @objc(URLSession:task:didCompleteWithError:) + func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + if let taskDidCompleteWithError = taskDidCompleteWithError { + taskDidCompleteWithError(session, task, error) + } else { + if let error = error { + if self.error == nil { self.error = error } + + if + let downloadDelegate = self as? DownloadTaskDelegate, + let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data + { + downloadDelegate.resumeData = resumeData + } + } + + queue.isSuspended = false + } + } +} + +// MARK: - + +class DataTaskDelegate: TaskDelegate, URLSessionDataDelegate { + + // MARK: Properties + + var dataTask: URLSessionDataTask { return task as! URLSessionDataTask } + + override var data: Data? { + if dataStream != nil { + return nil + } else { + return mutableData + } + } + + var progress: Progress + var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? + + var dataStream: ((_ data: Data) -> Void)? + + private var totalBytesReceived: Int64 = 0 + private var mutableData: Data + + private var expectedContentLength: Int64? + + // MARK: Lifecycle + + override init(task: URLSessionTask?) { + mutableData = Data() + progress = Progress(totalUnitCount: 0) + + super.init(task: task) + } + + override func reset() { + super.reset() + + progress = Progress(totalUnitCount: 0) + totalBytesReceived = 0 + mutableData = Data() + expectedContentLength = nil + } + + // MARK: URLSessionDataDelegate + + var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)? + var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)? + var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)? + var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)? + + func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didReceive response: URLResponse, + completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) + { + var disposition: URLSession.ResponseDisposition = .allow + + expectedContentLength = response.expectedContentLength + + if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse { + disposition = dataTaskDidReceiveResponse(session, dataTask, response) + } + + completionHandler(disposition) + } + + func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didBecome downloadTask: URLSessionDownloadTask) + { + dataTaskDidBecomeDownloadTask?(session, dataTask, downloadTask) + } + + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } + + if let dataTaskDidReceiveData = dataTaskDidReceiveData { + dataTaskDidReceiveData(session, dataTask, data) + } else { + if let dataStream = dataStream { + dataStream(data) + } else { + mutableData.append(data) + } + + let bytesReceived = Int64(data.count) + totalBytesReceived += bytesReceived + let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown + + progress.totalUnitCount = totalBytesExpected + progress.completedUnitCount = totalBytesReceived + + if let progressHandler = progressHandler { + progressHandler.queue.async { progressHandler.closure(self.progress) } + } + } + } + + func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + willCacheResponse proposedResponse: CachedURLResponse, + completionHandler: @escaping (CachedURLResponse?) -> Void) + { + var cachedResponse: CachedURLResponse? = proposedResponse + + if let dataTaskWillCacheResponse = dataTaskWillCacheResponse { + cachedResponse = dataTaskWillCacheResponse(session, dataTask, proposedResponse) + } + + completionHandler(cachedResponse) + } +} + +// MARK: - + +class DownloadTaskDelegate: TaskDelegate, URLSessionDownloadDelegate { + + // MARK: Properties + + var downloadTask: URLSessionDownloadTask { return task as! URLSessionDownloadTask } + + var progress: Progress + var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? + + var resumeData: Data? + override var data: Data? { return resumeData } + + var destination: DownloadRequest.DownloadFileDestination? + + var temporaryURL: URL? + var destinationURL: URL? + + var fileURL: URL? { return destination != nil ? destinationURL : temporaryURL } + + // MARK: Lifecycle + + override init(task: URLSessionTask?) { + progress = Progress(totalUnitCount: 0) + super.init(task: task) + } + + override func reset() { + super.reset() + + progress = Progress(totalUnitCount: 0) + resumeData = nil + } + + // MARK: URLSessionDownloadDelegate + + var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> URL)? + var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)? + var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)? + + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didFinishDownloadingTo location: URL) + { + temporaryURL = location + + guard + let destination = destination, + let response = downloadTask.response as? HTTPURLResponse + else { return } + + let result = destination(location, response) + let destinationURL = result.destinationURL + let options = result.options + + self.destinationURL = destinationURL + + do { + if options.contains(.removePreviousFile), FileManager.default.fileExists(atPath: destinationURL.path) { + try FileManager.default.removeItem(at: destinationURL) + } + + if options.contains(.createIntermediateDirectories) { + let directory = destinationURL.deletingLastPathComponent() + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + } + + try FileManager.default.moveItem(at: location, to: destinationURL) + } catch { + self.error = error + } + } + + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didWriteData bytesWritten: Int64, + totalBytesWritten: Int64, + totalBytesExpectedToWrite: Int64) + { + if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } + + if let downloadTaskDidWriteData = downloadTaskDidWriteData { + downloadTaskDidWriteData( + session, + downloadTask, + bytesWritten, + totalBytesWritten, + totalBytesExpectedToWrite + ) + } else { + progress.totalUnitCount = totalBytesExpectedToWrite + progress.completedUnitCount = totalBytesWritten + + if let progressHandler = progressHandler { + progressHandler.queue.async { progressHandler.closure(self.progress) } + } + } + } + + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didResumeAtOffset fileOffset: Int64, + expectedTotalBytes: Int64) + { + if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { + downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) + } else { + progress.totalUnitCount = expectedTotalBytes + progress.completedUnitCount = fileOffset + } + } +} + +// MARK: - + +class UploadTaskDelegate: DataTaskDelegate { + + // MARK: Properties + + var uploadTask: URLSessionUploadTask { return task as! URLSessionUploadTask } + + var uploadProgress: Progress + var uploadProgressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? + + // MARK: Lifecycle + + override init(task: URLSessionTask?) { + uploadProgress = Progress(totalUnitCount: 0) + super.init(task: task) + } + + override func reset() { + super.reset() + uploadProgress = Progress(totalUnitCount: 0) + } + + // MARK: URLSessionTaskDelegate + + var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)? + + func URLSession( + _ session: URLSession, + task: URLSessionTask, + didSendBodyData bytesSent: Int64, + totalBytesSent: Int64, + totalBytesExpectedToSend: Int64) + { + if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } + + if let taskDidSendBodyData = taskDidSendBodyData { + taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) + } else { + uploadProgress.totalUnitCount = totalBytesExpectedToSend + uploadProgress.completedUnitCount = totalBytesSent + + if let uploadProgressHandler = uploadProgressHandler { + uploadProgressHandler.queue.async { uploadProgressHandler.closure(self.uploadProgress) } + } + } + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Timeline.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Timeline.swift new file mode 100644 index 0000000..596c1bd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Timeline.swift @@ -0,0 +1,136 @@ +// +// Timeline.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// Responsible for computing the timing metrics for the complete lifecycle of a `Request`. +public struct Timeline { + /// The time the request was initialized. + public let requestStartTime: CFAbsoluteTime + + /// The time the first bytes were received from or sent to the server. + public let initialResponseTime: CFAbsoluteTime + + /// The time when the request was completed. + public let requestCompletedTime: CFAbsoluteTime + + /// The time when the response serialization was completed. + public let serializationCompletedTime: CFAbsoluteTime + + /// The time interval in seconds from the time the request started to the initial response from the server. + public let latency: TimeInterval + + /// The time interval in seconds from the time the request started to the time the request completed. + public let requestDuration: TimeInterval + + /// The time interval in seconds from the time the request completed to the time response serialization completed. + public let serializationDuration: TimeInterval + + /// The time interval in seconds from the time the request started to the time response serialization completed. + public let totalDuration: TimeInterval + + /// Creates a new `Timeline` instance with the specified request times. + /// + /// - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`. + /// - parameter initialResponseTime: The time the first bytes were received from or sent to the server. + /// Defaults to `0.0`. + /// - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`. + /// - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults + /// to `0.0`. + /// + /// - returns: The new `Timeline` instance. + public init( + requestStartTime: CFAbsoluteTime = 0.0, + initialResponseTime: CFAbsoluteTime = 0.0, + requestCompletedTime: CFAbsoluteTime = 0.0, + serializationCompletedTime: CFAbsoluteTime = 0.0) + { + self.requestStartTime = requestStartTime + self.initialResponseTime = initialResponseTime + self.requestCompletedTime = requestCompletedTime + self.serializationCompletedTime = serializationCompletedTime + + self.latency = initialResponseTime - requestStartTime + self.requestDuration = requestCompletedTime - requestStartTime + self.serializationDuration = serializationCompletedTime - requestCompletedTime + self.totalDuration = serializationCompletedTime - requestStartTime + } +} + +// MARK: - CustomStringConvertible + +extension Timeline: CustomStringConvertible { + /// The textual representation used when written to an output stream, which includes the latency, the request + /// duration and the total duration. + public var description: String { + let latency = String(format: "%.3f", self.latency) + let requestDuration = String(format: "%.3f", self.requestDuration) + let serializationDuration = String(format: "%.3f", self.serializationDuration) + let totalDuration = String(format: "%.3f", self.totalDuration) + + // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is + // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. + let timings = [ + "\"Latency\": " + latency + " secs", + "\"Request Duration\": " + requestDuration + " secs", + "\"Serialization Duration\": " + serializationDuration + " secs", + "\"Total Duration\": " + totalDuration + " secs" + ] + + return "Timeline: { " + timings.joined(separator: ", ") + " }" + } +} + +// MARK: - CustomDebugStringConvertible + +extension Timeline: CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, which includes the request start time, the + /// initial response time, the request completed time, the serialization completed time, the latency, the request + /// duration and the total duration. + public var debugDescription: String { + let requestStartTime = String(format: "%.3f", self.requestStartTime) + let initialResponseTime = String(format: "%.3f", self.initialResponseTime) + let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime) + let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime) + let latency = String(format: "%.3f", self.latency) + let requestDuration = String(format: "%.3f", self.requestDuration) + let serializationDuration = String(format: "%.3f", self.serializationDuration) + let totalDuration = String(format: "%.3f", self.totalDuration) + + // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is + // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. + let timings = [ + "\"Request Start Time\": " + requestStartTime, + "\"Initial Response Time\": " + initialResponseTime, + "\"Request Completed Time\": " + requestCompletedTime, + "\"Serialization Completed Time\": " + serializationCompletedTime, + "\"Latency\": " + latency + " secs", + "\"Request Duration\": " + requestDuration + " secs", + "\"Serialization Duration\": " + serializationDuration + " secs", + "\"Total Duration\": " + totalDuration + " secs" + ] + + return "Timeline: { " + timings.joined(separator: ", ") + " }" + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Validation.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Validation.swift new file mode 100644 index 0000000..5640789 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Alamofire/Source/Validation.swift @@ -0,0 +1,315 @@ +// +// Validation.swift +// +// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +extension Request { + + // MARK: Helper Types + + fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason + + /// Used to represent whether validation was successful or encountered an error resulting in a failure. + /// + /// - success: The validation was successful. + /// - failure: The validation failed encountering the provided error. + public enum ValidationResult { + case success + case failure(Error) + } + + fileprivate struct MIMEType { + let type: String + let subtype: String + + var isWildcard: Bool { return type == "*" && subtype == "*" } + + init?(_ string: String) { + let components: [String] = { + let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines) + + #if swift(>=3.2) + let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)] + #else + let split = stripped.substring(to: stripped.range(of: ";")?.lowerBound ?? stripped.endIndex) + #endif + + return split.components(separatedBy: "/") + }() + + if let type = components.first, let subtype = components.last { + self.type = type + self.subtype = subtype + } else { + return nil + } + } + + func matches(_ mime: MIMEType) -> Bool { + switch (type, subtype) { + case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"): + return true + default: + return false + } + } + } + + // MARK: Properties + + fileprivate var acceptableStatusCodes: [Int] { return Array(200..<300) } + + fileprivate var acceptableContentTypes: [String] { + if let accept = request?.value(forHTTPHeaderField: "Accept") { + return accept.components(separatedBy: ",") + } + + return ["*/*"] + } + + // MARK: Status Code + + fileprivate func validate( + statusCode acceptableStatusCodes: S, + response: HTTPURLResponse) + -> ValidationResult + where S.Iterator.Element == Int + { + if acceptableStatusCodes.contains(response.statusCode) { + return .success + } else { + let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode) + return .failure(AFError.responseValidationFailed(reason: reason)) + } + } + + // MARK: Content Type + + fileprivate func validate( + contentType acceptableContentTypes: S, + response: HTTPURLResponse, + data: Data?) + -> ValidationResult + where S.Iterator.Element == String + { + guard let data = data, data.count > 0 else { return .success } + + guard + let responseContentType = response.mimeType, + let responseMIMEType = MIMEType(responseContentType) + else { + for contentType in acceptableContentTypes { + if let mimeType = MIMEType(contentType), mimeType.isWildcard { + return .success + } + } + + let error: AFError = { + let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes)) + return AFError.responseValidationFailed(reason: reason) + }() + + return .failure(error) + } + + for contentType in acceptableContentTypes { + if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) { + return .success + } + } + + let error: AFError = { + let reason: ErrorReason = .unacceptableContentType( + acceptableContentTypes: Array(acceptableContentTypes), + responseContentType: responseContentType + ) + + return AFError.responseValidationFailed(reason: reason) + }() + + return .failure(error) + } +} + +// MARK: - + +extension DataRequest { + /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the + /// request was valid. + public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult + + /// Validates the request, using the specified closure. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter validation: A closure to validate the request. + /// + /// - returns: The request. + @discardableResult + public func validate(_ validation: @escaping Validation) -> Self { + let validationExecution: () -> Void = { [unowned self] in + if + let response = self.response, + self.delegate.error == nil, + case let .failure(error) = validation(self.request, response, self.delegate.data) + { + self.delegate.error = error + } + } + + validations.append(validationExecution) + + return self + } + + /// Validates that the response has a status code in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter range: The range of acceptable status codes. + /// + /// - returns: The request. + @discardableResult + public func validate(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int { + return validate { [unowned self] _, response, _ in + return self.validate(statusCode: acceptableStatusCodes, response: response) + } + } + + /// Validates that the response has a content type in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. + /// + /// - returns: The request. + @discardableResult + public func validate(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String { + return validate { [unowned self] _, response, data in + return self.validate(contentType: acceptableContentTypes, response: response, data: data) + } + } + + /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content + /// type matches any specified in the Accept HTTP header field. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - returns: The request. + @discardableResult + public func validate() -> Self { + return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes) + } +} + +// MARK: - + +extension DownloadRequest { + /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a + /// destination URL, and returns whether the request was valid. + public typealias Validation = ( + _ request: URLRequest?, + _ response: HTTPURLResponse, + _ temporaryURL: URL?, + _ destinationURL: URL?) + -> ValidationResult + + /// Validates the request, using the specified closure. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter validation: A closure to validate the request. + /// + /// - returns: The request. + @discardableResult + public func validate(_ validation: @escaping Validation) -> Self { + let validationExecution: () -> Void = { [unowned self] in + let request = self.request + let temporaryURL = self.downloadDelegate.temporaryURL + let destinationURL = self.downloadDelegate.destinationURL + + if + let response = self.response, + self.delegate.error == nil, + case let .failure(error) = validation(request, response, temporaryURL, destinationURL) + { + self.delegate.error = error + } + } + + validations.append(validationExecution) + + return self + } + + /// Validates that the response has a status code in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter range: The range of acceptable status codes. + /// + /// - returns: The request. + @discardableResult + public func validate(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int { + return validate { [unowned self] _, response, _, _ in + return self.validate(statusCode: acceptableStatusCodes, response: response) + } + } + + /// Validates that the response has a content type in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. + /// + /// - returns: The request. + @discardableResult + public func validate(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String { + return validate { [unowned self] _, response, _, _ in + let fileURL = self.downloadDelegate.fileURL + + guard let validFileURL = fileURL else { + return .failure(AFError.responseValidationFailed(reason: .dataFileNil)) + } + + do { + let data = try Data(contentsOf: validFileURL) + return self.validate(contentType: acceptableContentTypes, response: response, data: data) + } catch { + return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL))) + } + } + } + + /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content + /// type matches any specified in the Accept HTTP header field. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - returns: The request. + @discardableResult + public func validate() -> Self { + return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes) + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/LICENSE new file mode 100644 index 0000000..bb82a18 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Raizlabs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/README.md new file mode 100644 index 0000000..8c63c1b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/README.md @@ -0,0 +1,164 @@ +# Anchorage + +[![Swift 3.0 + 4.0](https://img.shields.io/badge/Swift-3.0%20+%204.0-orange.svg?style=flat)](https://swift.org) +[![CircleCI](https://img.shields.io/circleci/project/github/Raizlabs/Anchorage/master.svg)](https://circleci.com/gh/Raizlabs/Anchorage) +[![Version](https://img.shields.io/cocoapods/v/Anchorage.svg?style=flat)](https://cocoadocs.org/docsets/Anchorage) +[![Platform](https://img.shields.io/cocoapods/p/Anchorage.svg?style=flat)](http://cocoapods.org/pods/Anchorage) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + +A lightweight collection of intuitive operators and utilities that simplify Auto Layout code. Anchorage is built directly on top of the `NSLayoutAnchor` API. + +Each expression acts on one or more `NSLayoutAnchor`s, and returns active `NSLayoutConstraint`s. If you want inactive constraints, [here's how to do that](#batching-constraints). + +# Usage + +## Alignment + +```swift +// Pin the button to 12 pt from the leading edge of its container +button.leadingAnchor == container.leadingAnchor + 12 + +// Pin the button to at least 12 pt from the trailing edge of its container +button.trailingAnchor <= container.trailingAnchor - 12 + +// Center one or both axes of a view +button.centerXAnchor == container.centerXAnchor +button.centerAnchors == container.centerAnchors +``` + +## Relative Alignment + +```swift +// Position a view to be centered at 2/3 of its container's width +view.centerXAnchor == 2 * container.trailingAnchor / 3 + +// Pin the top of a view at 25% of container's height +view.topAnchor == container.bottomAnchor / 4 +``` + +## Sizing + +```swift +// Constrain a view's width to be at most 100 pt +view.widthAnchor <= 100 + +// Constraint a view to a fixed size +imageView.sizeAnchors == CGSize(width: 100, height: 200) + +// Constrain two views to be the same size +imageView.sizeAnchors == view.sizeAnchors + +// Constrain view to 4:3 aspect ratio +view.widthAnchor == 4 * view.heightAnchor / 3 +``` + +## Composite Anchors + +Constrain multiple edges at a time with this syntax: + +```swift +// Constrain the leading, trailing, top and bottom edges to be equal +imageView.edgeAnchors == container.edgeAnchors + +// Inset the edges of a view from another view +let insets = UIEdgeInsets(top: 5, left: 10, bottom: 15, right: 20) +imageView.edgeAnchors == container.edgeAnchors + insets + +// Inset the leading and trailing anchors by 10 +imageView.horizontalAnchors >= container.horizontalAnchors + 10 + +// Inset the top and bottom anchors by 10 +imageView.verticalAnchors >= container.verticalAnchors + 10 +``` + +#### Use leading and trailing +Using `leftAnchor` and `rightAnchor` is rarely the right choice. To encourage this, `horizontalAnchors` and `edgeAnchors` use the `leadingAnchor` and `trailingAnchor` layout anchors. + +#### Inset instead of Shift +When constraining leading/trailing or top/bottom, it is far more common to work in terms of an inset from the edges instead of shifting both edges in the same direction. When building the expression, Anchorage will flip the relationship and invert the constant in the constraint on the far side of the axis. This makes the expressions much more natural to work with. + + +## Priority + +The `~` is used to specify priority of the constraint resulting from any Anchorage expression: + +```swift +// Align view 20 points from the center of its superview, with system-defined low priority +view.centerXAnchor == view.superview.centerXAnchor + 20 ~ .low + +// Align view 20 points from the center of its superview, with (required - 1) priority +view.centerXAnchor == view.superview.centerXAnchor + 20 ~ .required - 1 + +// Align view 20 points from the center of its superview, with custom priority +view.centerXAnchor == view.superview.centerXAnchor + 20 ~ 752 +``` +The layout priority is an enum with the following values: + +- `.required` - `UILayoutPriorityRequired` (default) +- `.high` - `UILayoutPriorityDefaultHigh` +- `.low` - `UILayoutPriorityDefaultLow` +- `.fittingSize` - `UILayoutPriorityFittingSizeLevel` + +## Storing Constraints + +To store constraints created by Anchorage, simply assign the expression to a variable: + +```swift +// A single (active) NSLayoutConstraint +let topConstraint = (imageView.topAnchor == container.topAnchor) + +// EdgeConstraints represents a collection of constraints +// You can retrieve the NSLayoutConstraints individually, +// or get an [NSLayoutConstraint] via .all, .horizontal, or .vertical +let edgeConstraints = (button.edgeAnchors == container.edgeAnchors).all +``` + +## Batching Constraints + +By default, Anchorage returns active layout constraints. If you'd rather return inactive constraints for use with the [`NSLayoutConstraint.activate(_:)` method](https://developer.apple.com/reference/uikit/nslayoutconstraint/1526955-activate) for performance reasons, you can do it like this: + +```swift +let constraints = Anchorage.batch(active: false) { + view1.widthAnchor == view2.widthAnchor + view1.heightAnchor == view2.heightAnchor / 2 ~ .low + // ... as many constraints as you want +} + +// Later: +NSLayoutConstraint.activate(constraints) +``` + +You can also pass `active: true` if you want the constraints in the array to be automatically activated in a batch. + +## Autoresizing Mask + +Anchorage sets the `translatesAutoresizingMaskIntoConstraints` property to `false` on the *left* hand side of the expression, so you should never need to set this property manually. This is important to be aware of in case the container view relies on `translatesAutoresizingMaskIntoConstraints` being set to `true`. We tend to keep child views on the left hand side of the expression to avoid this problem, especially when constraining to a system-supplied view. + +# Installation + +## CocoaPods + +To integrate Anchorage into your Xcode project using CocoaPods, specify it in +your Podfile: + +```ruby +pod 'Anchorage' +``` + +## Carthage + +To integrate Anchorage into your Xcode project using Carthage, specify it in +your Cartfile: + +```ogdl +github "Raizlabs/Anchorage" +``` + +Run `carthage update` to build the framework and drag the built +`Anchorage.framework` into your Xcode project. + +# License + +This code and tool is under the MIT License. See `LICENSE` file in this repository. + +Any ideas and contributions welcome! diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/AnchorGroupProvider.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/AnchorGroupProvider.swift new file mode 100644 index 0000000..21f7bf2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/AnchorGroupProvider.swift @@ -0,0 +1,155 @@ +// +// AnchorGroupProvider.swift +// Anchorage +// +// Created by Rob Visentin on 5/1/17. +// +// Copyright 2016 Raizlabs and other contributors +// http://raizlabs.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#if os(macOS) + import Cocoa +#else + import UIKit +#endif + +public protocol AnchorGroupProvider { + + var horizontalAnchors: AnchorPair { get } + var verticalAnchors: AnchorPair { get } + var centerAnchors: AnchorPair { get } + var sizeAnchors: AnchorPair { get } + +} + +extension AnchorGroupProvider { + + public var edgeAnchors: EdgeAnchors { + return EdgeAnchors(horizontal: horizontalAnchors, vertical: verticalAnchors) + } + +} + +extension View: AnchorGroupProvider { + + public var horizontalAnchors: AnchorPair { + return AnchorPair(first: leadingAnchor, second: trailingAnchor) + } + + public var verticalAnchors: AnchorPair { + return AnchorPair(first: topAnchor, second: bottomAnchor) + } + + public var centerAnchors: AnchorPair { + return AnchorPair(first: centerXAnchor, second: centerYAnchor) + } + + public var sizeAnchors: AnchorPair { + return AnchorPair(first: widthAnchor, second: heightAnchor) + } + +} + +extension ViewController: AnchorGroupProvider { + + public var horizontalAnchors: AnchorPair { + return view.horizontalAnchors + } + + public var verticalAnchors: AnchorPair { +#if os(macOS) + return view.verticalAnchors +#else + return AnchorPair(first: topLayoutGuide.bottomAnchor, second: bottomLayoutGuide.topAnchor) +#endif + } + + public var centerAnchors: AnchorPair { + return view.centerAnchors + } + + public var sizeAnchors: AnchorPair { + return view.sizeAnchors + } + +} + +extension LayoutGuide: AnchorGroupProvider { + + public var horizontalAnchors: AnchorPair { + return AnchorPair(first: leadingAnchor, second: trailingAnchor) + } + + public var verticalAnchors: AnchorPair { + return AnchorPair(first: topAnchor, second: bottomAnchor) + } + + public var centerAnchors: AnchorPair { + return AnchorPair(first: centerXAnchor, second: centerYAnchor) + } + + public var sizeAnchors: AnchorPair { + return AnchorPair(first: widthAnchor, second: heightAnchor) + } + +} + +// MARK: - EdgeAnchors + +public struct EdgeAnchors: LayoutAnchorType { + + public var horizontalAnchors: AnchorPair + public var verticalAnchors: AnchorPair + +} + +// MARK: - Axis Group + +public struct ConstraintPair { + + public var first: NSLayoutConstraint + public var second: NSLayoutConstraint + +} + +// MARK: - ConstraintGroup + +public struct ConstraintGroup { + + public var top: NSLayoutConstraint + public var leading: NSLayoutConstraint + public var bottom: NSLayoutConstraint + public var trailing: NSLayoutConstraint + + public var horizontal: [NSLayoutConstraint] { + return [leading, trailing] + } + + public var vertical: [NSLayoutConstraint] { + return [top, bottom] + } + + public var all: [NSLayoutConstraint] { + return [top, leading, bottom, trailing] + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Anchorage.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Anchorage.swift new file mode 100644 index 0000000..afa1358 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Anchorage.swift @@ -0,0 +1,425 @@ +// +// Anchorage.swift +// Anchorage +// +// Created by Rob Visentin on 2/6/16. +// +// Copyright 2016 Raizlabs and other contributors +// http://raizlabs.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#if os(macOS) + import Cocoa +#else + import UIKit +#endif + +public protocol LayoutConstantType {} +extension CGFloat: LayoutConstantType {} +extension CGSize: LayoutConstantType {} +extension EdgeInsets: LayoutConstantType {} + +public protocol LayoutAnchorType {} +extension NSLayoutAnchor: LayoutAnchorType {} + +// MARK: - Equality Constraints + +@discardableResult public func == (lhs: NSLayoutDimension, rhs: T) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(equalToConstant: CGFloat(rhs))) +} + +@discardableResult public func == (lhs: NSLayoutXAxisAnchor, rhs: NSLayoutXAxisAnchor) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(equalTo: rhs)) +} + +@discardableResult public func == (lhs: NSLayoutYAxisAnchor, rhs: NSLayoutYAxisAnchor) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(equalTo: rhs)) +} + +@discardableResult public func == (lhs: NSLayoutDimension, rhs: NSLayoutDimension) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(equalTo: rhs)) +} + +@discardableResult public func == (lhs: NSLayoutXAxisAnchor, rhs: LayoutExpression) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(equalTo: rhs.anchor!, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) +} + +@discardableResult public func == (lhs: NSLayoutYAxisAnchor, rhs: LayoutExpression) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(equalTo: rhs.anchor!, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) +} + +@discardableResult public func == (lhs: NSLayoutDimension, rhs: LayoutExpression) -> NSLayoutConstraint { + if let anchor = rhs.anchor { + return finalize(constraint: lhs.constraint(equalTo: anchor, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) + } + else { + return finalize(constraint: lhs.constraint(equalToConstant: rhs.constant), withPriority: rhs.priority) + } +} + +@discardableResult public func == (lhs: EdgeAnchors, rhs: EdgeAnchors) -> ConstraintGroup { + return lhs.finalize(constraintsEqualToEdges: rhs) +} + +@discardableResult public func == (lhs: EdgeAnchors, rhs: LayoutExpression) -> ConstraintGroup { + return lhs.finalize(constraintsEqualToEdges: rhs.anchor, constant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func == (lhs: EdgeAnchors, rhs: LayoutExpression) -> ConstraintGroup { + return lhs.finalize(constraintsEqualToEdges: rhs.anchor, insets: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func == (lhs: AnchorPair, rhs: AnchorPair) -> ConstraintPair { + return lhs.finalize(constraintsEqualToEdges: rhs) +} + +@discardableResult public func == (lhs: AnchorPair, rhs: LayoutExpression, CGFloat>) -> ConstraintPair { + return lhs.finalize(constraintsEqualToEdges: rhs.anchor, constant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func == (lhs: AnchorPair, rhs: CGSize) -> ConstraintPair { + return lhs.finalize(constraintsEqualToConstant: rhs) +} + +@discardableResult public func == (lhs: AnchorPair, rhs: LayoutExpression, CGSize>) -> ConstraintPair { + return lhs.finalize(constraintsEqualToConstant: rhs.constant, priority: rhs.priority) +} + +// MARK: - Inequality Constraints + +@discardableResult public func <= (lhs: NSLayoutDimension, rhs: T) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(lessThanOrEqualToConstant: CGFloat(rhs))) +} + +@discardableResult public func <= (lhs: NSLayoutXAxisAnchor, rhs: NSLayoutXAxisAnchor) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(lessThanOrEqualTo: rhs)) +} + +@discardableResult public func <= (lhs: NSLayoutYAxisAnchor, rhs: NSLayoutYAxisAnchor) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(lessThanOrEqualTo: rhs)) +} + +@discardableResult public func <= (lhs: NSLayoutDimension, rhs: NSLayoutDimension) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(lessThanOrEqualTo: rhs)) +} + +@discardableResult public func <= (lhs: NSLayoutXAxisAnchor, rhs: LayoutExpression) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(lessThanOrEqualTo: rhs.anchor!, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) +} + +@discardableResult public func <= (lhs: NSLayoutYAxisAnchor, rhs: LayoutExpression) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(lessThanOrEqualTo: rhs.anchor!, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) +} + +@discardableResult public func <= (lhs: NSLayoutDimension, rhs: LayoutExpression) -> NSLayoutConstraint { + if let anchor = rhs.anchor { + return finalize(constraint: lhs.constraint(lessThanOrEqualTo: anchor, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) + } + else { + return finalize(constraint: lhs.constraint(lessThanOrEqualToConstant: rhs.constant), withPriority: rhs.priority) + } +} + +@discardableResult public func <= (lhs: EdgeAnchors, rhs: EdgeAnchors) -> ConstraintGroup { + return lhs.finalize(constraintsLessThanOrEqualToEdges: rhs) +} + +@discardableResult public func <= (lhs: EdgeAnchors, rhs: LayoutExpression) -> ConstraintGroup { + return lhs.finalize(constraintsLessThanOrEqualToEdges: rhs.anchor, constant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func <= (lhs: EdgeAnchors, rhs: LayoutExpression) -> ConstraintGroup { + return lhs.finalize(constraintsLessThanOrEqualToEdges: rhs.anchor, insets: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func <= (lhs: AnchorPair, rhs: AnchorPair) -> ConstraintPair { + return lhs.finalize(constraintsLessThanOrEqualToEdges: rhs) +} + +@discardableResult public func <= (lhs: AnchorPair, rhs: LayoutExpression, CGFloat>) -> ConstraintPair { + return lhs.finalize(constraintsLessThanOrEqualToEdges: rhs.anchor, constant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func <= (lhs: AnchorPair, rhs: CGSize) -> ConstraintPair { + return lhs.finalize(constraintsLessThanOrEqualToConstant: rhs) +} + +@discardableResult public func <= (lhs: AnchorPair, rhs: LayoutExpression, CGSize>) -> ConstraintPair { + return lhs.finalize(constraintsLessThanOrEqualToConstant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func >= (lhs: NSLayoutDimension, rhs: T) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(greaterThanOrEqualToConstant: CGFloat(rhs))) +} + +@discardableResult public func >= (lhs: NSLayoutXAxisAnchor, rhs: NSLayoutXAxisAnchor) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(greaterThanOrEqualTo: rhs)) +} + +@discardableResult public func >= (lhs: NSLayoutYAxisAnchor, rhs: NSLayoutYAxisAnchor) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(greaterThanOrEqualTo: rhs)) +} + +@discardableResult public func >= (lhs: NSLayoutDimension, rhs: NSLayoutDimension) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(greaterThanOrEqualTo: rhs)) +} + +@discardableResult public func >= (lhs: NSLayoutXAxisAnchor, rhs: LayoutExpression) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(greaterThanOrEqualTo: rhs.anchor!, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) +} + +@discardableResult public func >= (lhs: NSLayoutYAxisAnchor, rhs: LayoutExpression) -> NSLayoutConstraint { + return finalize(constraint: lhs.constraint(greaterThanOrEqualTo: rhs.anchor!, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) +} + +@discardableResult public func >= (lhs: NSLayoutDimension, rhs: LayoutExpression) -> NSLayoutConstraint { + if let anchor = rhs.anchor { + return finalize(constraint: lhs.constraint(greaterThanOrEqualTo: anchor, multiplier: rhs.multiplier, constant: rhs.constant), withPriority: rhs.priority) + } + else { + return finalize(constraint: lhs.constraint(greaterThanOrEqualToConstant: rhs.constant), withPriority: rhs.priority) + } +} + +@discardableResult public func >= (lhs: EdgeAnchors, rhs: EdgeAnchors) -> ConstraintGroup { + return lhs.finalize(constraintsGreaterThanOrEqualToEdges: rhs) +} + +@discardableResult public func >= (lhs: EdgeAnchors, rhs: LayoutExpression) -> ConstraintGroup { + return lhs.finalize(constraintsGreaterThanOrEqualToEdges: rhs.anchor, constant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func >= (lhs: EdgeAnchors, rhs: LayoutExpression) -> ConstraintGroup { + return lhs.finalize(constraintsGreaterThanOrEqualToEdges: rhs.anchor, insets: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func >= (lhs: AnchorPair, rhs: AnchorPair) -> ConstraintPair { + return lhs.finalize(constraintsGreaterThanOrEqualToEdges: rhs) +} + +@discardableResult public func >= (lhs: AnchorPair, rhs: LayoutExpression, CGFloat>) -> ConstraintPair { + return lhs.finalize(constraintsGreaterThanOrEqualToEdges: rhs.anchor, constant: rhs.constant, priority: rhs.priority) +} + +@discardableResult public func >= (lhs: AnchorPair, rhs: CGSize) -> ConstraintPair { + return lhs.finalize(constraintsGreaterThanOrEqualToConstant: rhs) +} + +@discardableResult public func >= (lhs: AnchorPair, rhs: LayoutExpression, CGSize>) -> ConstraintPair { + return lhs.finalize(constraintsGreaterThanOrEqualToConstant: rhs.constant, priority: rhs.priority) +} + +// MARK: - Priority + +precedencegroup PriorityPrecedence { + associativity: none + higherThan: ComparisonPrecedence + lowerThan: AdditionPrecedence +} + +infix operator ~: PriorityPrecedence + +@discardableResult public func ~ (lhs: T, rhs: Priority) -> LayoutExpression { + return LayoutExpression(constant: CGFloat(lhs), priority: rhs) +} + +@discardableResult public func ~ (lhs: CGSize, rhs: Priority) -> LayoutExpression, CGSize> { + return LayoutExpression(constant: lhs, priority: rhs) +} + +@discardableResult public func ~ (lhs: T, rhs: Priority) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: 0.0, priority: rhs) +} + +@discardableResult public func ~ (lhs: LayoutExpression, rhs: Priority) -> LayoutExpression { + var expr = lhs + expr.priority = rhs + return expr +} + +@discardableResult public func * (lhs: NSLayoutDimension, rhs: T) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: 0.0, multiplier: CGFloat(rhs)) +} + +@discardableResult public func * (lhs: T, rhs: NSLayoutDimension) -> LayoutExpression { + return LayoutExpression(anchor: rhs, constant: 0.0, multiplier: CGFloat(lhs)) +} + +@discardableResult public func * (lhs: LayoutExpression, rhs: T) -> LayoutExpression { + var expr = lhs + expr.multiplier *= CGFloat(rhs) + return expr +} + +@discardableResult public func * (lhs: T, rhs: LayoutExpression) -> LayoutExpression { + var expr = rhs + expr.multiplier *= CGFloat(lhs) + return expr +} + +@discardableResult public func * (lhs: NSLayoutXAxisAnchor, rhs: T) -> LayoutExpression { + return LayoutExpression(anchor: Optional.some(lhs), constant: 0.0, multiplier: CGFloat(rhs)) +} + +@discardableResult public func * (lhs: T, rhs: NSLayoutXAxisAnchor) -> LayoutExpression { + return LayoutExpression(anchor: rhs, constant: 0.0, multiplier: CGFloat(lhs)) +} + +@discardableResult public func * (lhs: LayoutExpression, rhs: T) -> LayoutExpression { + var expr = lhs + expr.multiplier *= CGFloat(rhs) + return expr +} + +@discardableResult public func * (lhs: T, rhs: LayoutExpression) -> LayoutExpression { + var expr = rhs + expr.multiplier *= CGFloat(lhs) + return expr +} + +@discardableResult public func * (lhs: NSLayoutYAxisAnchor, rhs: T) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: 0.0, multiplier: CGFloat(rhs)) +} + +@discardableResult public func * (lhs: T, rhs: NSLayoutYAxisAnchor) -> LayoutExpression { + return LayoutExpression(anchor: rhs, constant: 0.0, multiplier: CGFloat(lhs)) +} + +@discardableResult public func * (lhs: LayoutExpression, rhs: T) -> LayoutExpression { + var expr = lhs + expr.multiplier *= CGFloat(rhs) + return expr +} + +@discardableResult public func * (lhs: T, rhs: LayoutExpression) -> LayoutExpression { + var expr = rhs + expr.multiplier *= CGFloat(lhs) + return expr +} + +@discardableResult public func / (lhs: NSLayoutDimension, rhs: T) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: 0.0, multiplier: 1.0 / CGFloat(rhs)) +} + +@discardableResult public func / (lhs: LayoutExpression, rhs: T) -> LayoutExpression { + var expr = lhs + expr.multiplier /= CGFloat(rhs) + return expr +} + +@discardableResult public func / (lhs: NSLayoutXAxisAnchor, rhs: T) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: 0.0, multiplier: 1.0 / CGFloat(rhs)) +} + +@discardableResult public func / (lhs: LayoutExpression, rhs: T) -> LayoutExpression { + var expr = lhs + expr.multiplier /= CGFloat(rhs) + return expr +} + +@discardableResult public func / (lhs: NSLayoutYAxisAnchor, rhs: T) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: 0.0, multiplier: 1.0 / CGFloat(rhs)) +} + +@discardableResult public func / (lhs: LayoutExpression, rhs: T) -> LayoutExpression { + var expr = lhs + expr.multiplier /= CGFloat(rhs) + return expr +} + +@discardableResult public func + (lhs: T, rhs: U) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: CGFloat(rhs)) +} + +@discardableResult public func + (lhs: T, rhs: U) -> LayoutExpression { + return LayoutExpression(anchor: rhs, constant: CGFloat(lhs)) +} + +@discardableResult public func + (lhs: LayoutExpression, rhs: U) -> LayoutExpression { + var expr = lhs + expr.constant += CGFloat(rhs) + return expr +} + +@discardableResult public func + (lhs: T, rhs: LayoutExpression) -> LayoutExpression { + var expr = rhs + expr.constant += CGFloat(lhs) + return expr +} + +@discardableResult public func + (lhs: EdgeAnchors, rhs: EdgeInsets) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: rhs) +} + +@discardableResult public func - (lhs: T, rhs: U) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: -CGFloat(rhs)) +} + +@discardableResult public func - (lhs: T, rhs: U) -> LayoutExpression { + return LayoutExpression(anchor: rhs, constant: -CGFloat(lhs)) +} + +@discardableResult public func - (lhs: LayoutExpression, rhs: U) -> LayoutExpression { + var expr = lhs + expr.constant -= CGFloat(rhs) + return expr +} + +@discardableResult public func - (lhs: T, rhs: LayoutExpression) -> LayoutExpression { + var expr = rhs + expr.constant -= CGFloat(lhs) + return expr +} + +@discardableResult public func - (lhs: EdgeAnchors, rhs: EdgeInsets) -> LayoutExpression { + return LayoutExpression(anchor: lhs, constant: -rhs) +} + +// MARK: - Batching + +/// Any Anchorage constraints created inside the passed closure are returned in the array. +/// +/// - Parameter closure: A closure that runs some Anchorage expressions. +/// - Returns: An array of new, active `NSLayoutConstraint`s. +@discardableResult public func batch(_ closure: () -> Void) -> [NSLayoutConstraint] { + return batch(active: true, closure: closure) +} + +/// Any Anchorage constraints created inside the passed closure are returned in the array. +/// +/// - Parameter active: Whether the created constraints should be active when they are returned. +/// - Parameter closure: A closure that runs some Anchorage expressions. +/// - Returns: An array of new `NSLayoutConstraint`s. +public func batch(active: Bool, closure: () -> Void) -> [NSLayoutConstraint] { + let batch = ConstraintBatch() + batches.append(batch) + defer { + batches.removeLast() + } + + closure() + + if active { + batch.activate() + } + + return batch.constraints +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Compatability.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Compatability.swift new file mode 100644 index 0000000..1b5a74f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Compatability.swift @@ -0,0 +1,112 @@ +// +// Compatability.swift +// Anchorage +// +// Created by Rob Visentin on 5/1/17. +// +// Copyright 2016 Raizlabs and other contributors +// http://raizlabs.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#if os(macOS) + import Cocoa + + #if swift(>=4.0) + public typealias LayoutPriority = NSLayoutConstraint.Priority + public typealias EdgeInsets = NSEdgeInsets + #else + public typealias LayoutPriority = NSLayoutPriority + #endif +#else + import UIKit + + public typealias LayoutPriority = UILayoutPriority + public typealias EdgeInsets = UIEdgeInsets +#endif + +#if swift(>=4.2) || (os(macOS) && swift(>=4.0)) + public typealias ConstraintAttribute = NSLayoutConstraint.Attribute +#else + public typealias ConstraintAttribute = NSLayoutAttribute +#endif + +#if swift(>=4.0) +#else + extension LayoutPriority { + + var rawValue: Float { + return self + } + + init(rawValue: Float) { + self.init(rawValue) + } + } +#endif + +#if swift(>=4.2) +#elseif !os(macOS) + extension UITableView { + public static let automaticDimension = UITableViewAutomaticDimension + } + + extension UITableViewCell { + public typealias CellStyle = UITableViewCellStyle + } + + extension UIApplication { + public typealias LaunchOptionsKey = UIApplicationLaunchOptionsKey + } +#endif + +extension CGFloat { + + init(_ value: T) { + switch value { + case is Double: + self.init(value as! Double) + case is Float: + self.init(value as! Float) + case is CGFloat: + self.init(value as! CGFloat) + default: + fatalError("Unable to initialize CGFloat with value \(value) of type \(type(of: value))") + } + } + +} + +extension Float { + + init(_ value: T) { + switch value { + case is Double: + self.init(value as! Double) + case is Float: + self.init(value as! Float) + case is CGFloat: + self.init(value as! CGFloat) + default: + fatalError("Unable to initialize CGFloat with value \(value) of type \(type(of: value))") + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Internal.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Internal.swift new file mode 100644 index 0000000..d23e006 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Internal.swift @@ -0,0 +1,364 @@ +// +// Internal.swift +// Anchorage +// +// Created by Rob Visentin on 5/1/17. +// +// Copyright 2016 Raizlabs and other contributors +// http://raizlabs.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#if os(macOS) + import Cocoa + + internal typealias View = NSView + internal typealias ViewController = NSViewController + internal typealias LayoutGuide = NSLayoutGuide + + #if swift(>=4.0) + internal let LayoutPriorityRequired = NSLayoutConstraint.Priority.required + internal let LayoutPriorityHigh = NSLayoutConstraint.Priority.defaultHigh + internal let LayoutPriorityLow = NSLayoutConstraint.Priority.defaultLow + internal let LayoutPriorityFittingSize = NSLayoutConstraint.Priority.fittingSizeCompression + #else + internal let LayoutPriorityRequired = NSLayoutPriorityRequired + internal let LayoutPriorityHigh = NSLayoutPriorityDefaultHigh + internal let LayoutPriorityLow = NSLayoutPriorityDefaultLow + internal let LayoutPriorityFittingSize = NSLayoutPriorityFittingSizeCompression + #endif +#else + import UIKit + + internal typealias View = UIView + internal typealias ViewController = UIViewController + internal typealias LayoutGuide = UILayoutGuide + + #if swift(>=4.0) + internal let LayoutPriorityRequired = UILayoutPriority.required + internal let LayoutPriorityHigh = UILayoutPriority.defaultHigh + internal let LayoutPriorityLow = UILayoutPriority.defaultLow + internal let LayoutPriorityFittingSize = UILayoutPriority.fittingSizeLevel + #else + internal let LayoutPriorityRequired = UILayoutPriorityRequired + internal let LayoutPriorityHigh = UILayoutPriorityDefaultHigh + internal let LayoutPriorityLow = UILayoutPriorityDefaultLow + internal let LayoutPriorityFittingSize = UILayoutPriorityFittingSizeLevel + #endif +#endif + +// MARK: - LayoutExpression + +public struct LayoutExpression { + + public var anchor: T? + public var constant: U + public var multiplier: CGFloat + public var priority: Priority + + internal init(anchor: T? = nil, constant: U, multiplier: CGFloat = 1.0, priority: Priority = .required) { + self.anchor = anchor + self.constant = constant + self.multiplier = multiplier + self.priority = priority + } + +} + +// MARK: - AnchorPair + +public struct AnchorPair: LayoutAnchorType { + + public var first: T + public var second: U + + public init(first: T, second: U) { + self.first = first + self.second = second + } + +} + +internal extension AnchorPair { + + func finalize(constraintsEqualToConstant size: CGSize, priority: Priority = .required) -> ConstraintPair { + return constraints(forConstant: size, priority: priority, builder: ConstraintBuilder.equality); + } + + func finalize(constraintsLessThanOrEqualToConstant size: CGSize, priority: Priority = .required) -> ConstraintPair { + return constraints(forConstant: size, priority: priority, builder: ConstraintBuilder.lessThanOrEqual); + } + + func finalize(constraintsGreaterThanOrEqualToConstant size: CGSize, priority: Priority = .required) -> ConstraintPair { + return constraints(forConstant: size, priority: priority, builder: ConstraintBuilder.greaterThanOrEqual); + } + + func finalize(constraintsEqualToEdges anchor: AnchorPair?, constant c: CGFloat = 0.0, priority: Priority = .required) -> ConstraintPair { + return constraints(forAnchors: anchor, constant: c, priority: priority, builder: ConstraintBuilder.equality) + } + + func finalize(constraintsLessThanOrEqualToEdges anchor: AnchorPair?, constant c: CGFloat = 0.0, priority: Priority = .required) -> ConstraintPair { + return constraints(forAnchors: anchor, constant: c, priority: priority, builder: ConstraintBuilder.lessThanOrEqual) + } + + func finalize(constraintsGreaterThanOrEqualToEdges anchor: AnchorPair?, constant c: CGFloat = 0.0, priority: Priority = .required) -> ConstraintPair { + return constraints(forAnchors: anchor, constant: c, priority: priority, builder: ConstraintBuilder.greaterThanOrEqual) + } + + func constraints(forConstant size: CGSize, priority: Priority, builder: ConstraintBuilder) -> ConstraintPair { + var constraints: ConstraintPair! + + performInBatch { + switch (first, second) { + case let (first as NSLayoutDimension, second as NSLayoutDimension): + constraints = ConstraintPair( + first: builder.dimensionBuilder(first, size.width ~ priority), + second: builder.dimensionBuilder(second, size.height ~ priority) + ) + default: + preconditionFailure("Only AnchorPair can be constrained to a constant size.") + } + } + + return constraints; + } + + func constraints(forAnchors anchors: AnchorPair?, constant c: CGFloat, priority: Priority, builder: ConstraintBuilder) -> ConstraintPair { + return constraints(forAnchors: anchors, firstConstant: c, secondConstant: c, priority: priority, builder: builder) + } + + func constraints(forAnchors anchors: AnchorPair?, firstConstant c1: CGFloat, secondConstant c2: CGFloat, priority: Priority, builder: ConstraintBuilder) -> ConstraintPair { + guard let anchors = anchors else { + preconditionFailure("Encountered nil edge anchors, indicating internal inconsistency of this API.") + } + + var constraints: ConstraintPair! + + performInBatch { + switch (first, anchors.first, second, anchors.second) { + // Leading, Trailing + case let (firstX as NSLayoutXAxisAnchor, otherFirstX as NSLayoutXAxisAnchor, + secondX as NSLayoutXAxisAnchor, otherSecondX as NSLayoutXAxisAnchor): + constraints = ConstraintPair( + first: builder.leadingBuilder(firstX, otherFirstX + c1 ~ priority), + second: builder.trailingBuilder(secondX, otherSecondX - c2 ~ priority) + ) + // Top, Bottom + case let (firstY as NSLayoutYAxisAnchor, otherFirstY as NSLayoutYAxisAnchor, + secondY as NSLayoutYAxisAnchor, otherSecondY as NSLayoutYAxisAnchor): + constraints = ConstraintPair( + first: builder.topBuilder(firstY, otherFirstY + c1 ~ priority), + second: builder.bottomBuilder(secondY, otherSecondY - c2 ~ priority) + ) + // CenterX, CenterY + case let (firstX as NSLayoutXAxisAnchor, otherFirstX as NSLayoutXAxisAnchor, + firstY as NSLayoutYAxisAnchor, otherFirstY as NSLayoutYAxisAnchor): + constraints = ConstraintPair( + first: builder.centerXBuilder(firstX, otherFirstX + c1 ~ priority), + second: builder.centerYBuilder(firstY, otherFirstY + c2 ~ priority) + ) + // Width, Height + case let (first as NSLayoutDimension, otherFirst as NSLayoutDimension, + second as NSLayoutDimension, otherSecond as NSLayoutDimension): + constraints = ConstraintPair( + first: builder.dimensionBuilder(first, otherFirst + c1 ~ priority), + second: builder.dimensionBuilder(second, otherSecond + c2 ~ priority) + ) + default: + preconditionFailure("Constrained anchors must match in either axis or type.") + } + } + + return constraints + } + +} + +// MARK: - EdgeAnchors + +internal extension EdgeInsets { + + init(constant: CGFloat) { + self.init( + top: constant, + left: constant, + bottom: constant, + right: constant + ) + } + +} + +internal prefix func - (rhs: EdgeInsets) -> EdgeInsets { + return EdgeInsets( + top: -rhs.top, + left: -rhs.left, + bottom: -rhs.bottom, + right: -rhs.right + ) +} + +internal extension EdgeAnchors { + + init(horizontal: AnchorPair, vertical: AnchorPair) { + self.horizontalAnchors = horizontal + self.verticalAnchors = vertical + } + + func finalize(constraintsEqualToEdges anchor: EdgeAnchors?, insets: EdgeInsets, priority: Priority = .required) -> ConstraintGroup { + return constraints(forAnchors: anchor, insets: insets, priority: priority, builder: ConstraintBuilder.equality) + } + + func finalize(constraintsLessThanOrEqualToEdges anchor: EdgeAnchors?, insets: EdgeInsets, priority: Priority = .required) -> ConstraintGroup { + return constraints(forAnchors: anchor, insets: insets, priority: priority, builder: ConstraintBuilder.lessThanOrEqual) + } + + func finalize(constraintsGreaterThanOrEqualToEdges anchor: EdgeAnchors?, insets: EdgeInsets, priority: Priority = .required) -> ConstraintGroup { + return constraints(forAnchors: anchor, insets: insets, priority: priority, builder: ConstraintBuilder.greaterThanOrEqual) + } + + func finalize(constraintsEqualToEdges anchor: EdgeAnchors?, constant c: CGFloat = 0.0, priority: Priority = .required) -> ConstraintGroup { + return constraints(forAnchors: anchor, insets: EdgeInsets(constant: c), priority: priority, builder: ConstraintBuilder.equality) + } + + func finalize(constraintsLessThanOrEqualToEdges anchor: EdgeAnchors?, constant c: CGFloat = 0.0, priority: Priority = .required) -> ConstraintGroup { + return constraints(forAnchors: anchor, insets: EdgeInsets(constant: c), priority: priority, builder: ConstraintBuilder.lessThanOrEqual) + } + + func finalize(constraintsGreaterThanOrEqualToEdges anchor: EdgeAnchors?, constant c: CGFloat = 0.0, priority: Priority = .required) -> ConstraintGroup { + return constraints(forAnchors: anchor, insets: EdgeInsets(constant: c), priority: priority, builder: ConstraintBuilder.greaterThanOrEqual) + } + + func constraints(forAnchors anchors: EdgeAnchors?, insets: EdgeInsets, priority: Priority, builder: ConstraintBuilder) -> ConstraintGroup { + guard let anchors = anchors else { + preconditionFailure("Encountered nil edge anchors, indicating internal inconsistency of this API.") + } + + var constraints: ConstraintGroup! + + performInBatch { + let horizontalConstraints = horizontalAnchors.constraints(forAnchors: anchors.horizontalAnchors, firstConstant: insets.left, secondConstant: insets.right, priority: priority, builder: builder) + let verticalConstraints = verticalAnchors.constraints(forAnchors: anchors.verticalAnchors, firstConstant: insets.top, secondConstant: insets.bottom, priority: priority, builder: builder) + constraints = ConstraintGroup( + top: verticalConstraints.first, + leading: horizontalConstraints.first, + bottom: verticalConstraints.second, + trailing: horizontalConstraints.second + ) + } + + return constraints + } + +} + +// MARK: - ConstraintBuilder + +internal struct ConstraintBuilder { + + typealias Horizontal = (NSLayoutXAxisAnchor, LayoutExpression) -> NSLayoutConstraint + typealias Vertical = (NSLayoutYAxisAnchor, LayoutExpression) -> NSLayoutConstraint + typealias Dimension = (NSLayoutDimension, LayoutExpression) -> NSLayoutConstraint + + static let equality = ConstraintBuilder(horizontal: ==, vertical: ==, dimension: ==) + static let lessThanOrEqual = ConstraintBuilder(leading: <=, top: <=, trailing: >=, bottom: >=, centerX: <=, centerY: <=, dimension: <=) + static let greaterThanOrEqual = ConstraintBuilder(leading: >=, top: >=, trailing: <=, bottom: <=, centerX: >=, centerY: >=, dimension: >=) + + var topBuilder: Vertical + var leadingBuilder: Horizontal + var bottomBuilder: Vertical + var trailingBuilder: Horizontal + var centerYBuilder: Vertical + var centerXBuilder: Horizontal + var dimensionBuilder: Dimension + + init(horizontal: @escaping Horizontal, vertical: @escaping Vertical, dimension: @escaping Dimension) { + topBuilder = vertical + leadingBuilder = horizontal + bottomBuilder = vertical + trailingBuilder = horizontal + centerYBuilder = vertical + centerXBuilder = horizontal + dimensionBuilder = dimension + } + + init(leading: @escaping Horizontal, top: @escaping Vertical, trailing: @escaping Horizontal, + bottom: @escaping Vertical, centerX: @escaping Horizontal, centerY: @escaping Vertical, dimension: @escaping Dimension) { + leadingBuilder = leading + topBuilder = top + trailingBuilder = trailing + bottomBuilder = bottom + centerYBuilder = centerY + centerXBuilder = centerX + dimensionBuilder = dimension + } + +} + +// MARK: - Batching + +internal var batches: [ConstraintBatch] = [] + +internal class ConstraintBatch { + + var constraints = [NSLayoutConstraint]() + + func add(constraint: NSLayoutConstraint) { + constraints.append(constraint) + } + + func activate() { + NSLayoutConstraint.activate(constraints) + } + +} + +/// Perform a closure immediately if a batch is already active, +/// otherwise executes the closure in a new batch. +/// +/// - Parameter closure: The work to perform inside of a batch +internal func performInBatch(closure: () -> Void) { + if batches.isEmpty { + batch(closure) + } + else { + closure() + } +} + +// MARK: - Constraint Activation + +internal func finalize(constraint: NSLayoutConstraint, withPriority priority: Priority = .required) -> NSLayoutConstraint { + // Only disable autoresizing constraints on the LHS item, which is the one definitely intended to be governed by Auto Layout + if let first = constraint.firstItem as? View { + first.translatesAutoresizingMaskIntoConstraints = false + } + + constraint.priority = priority.value + + if let lastBatch = batches.last { + lastBatch.add(constraint: constraint) + } + else { + constraint.isActive = true + } + + return constraint +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/NSLayoutAnchor+MultiplierConstraints.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/NSLayoutAnchor+MultiplierConstraints.swift new file mode 100644 index 0000000..177c86e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/NSLayoutAnchor+MultiplierConstraints.swift @@ -0,0 +1,91 @@ +// +// NSLayoutAnchor+MultiplierConstraints.swift +// Anchorage +// +// Created by Aleksandr Gusev on 7/21/17. +// +// Copyright 2016 Raizlabs and other contributors +// http://raizlabs.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#if os(macOS) + import Cocoa +#else + import UIKit +#endif + +extension NSLayoutXAxisAnchor { + func constraint(equalTo anchor: NSLayoutXAxisAnchor, + multiplier m: CGFloat, + constant c: CGFloat = 0.0) -> NSLayoutConstraint { + let constraint = self.constraint(equalTo: anchor, constant: c) + return constraint.with(multiplier: m) + } + + func constraint(greaterThanOrEqualTo anchor: NSLayoutXAxisAnchor, + multiplier m: CGFloat, + constant c: CGFloat = 0.0) -> NSLayoutConstraint { + let constraint = self.constraint(greaterThanOrEqualTo: anchor, constant: c) + return constraint.with(multiplier: m) + } + + func constraint(lessThanOrEqualTo anchor: NSLayoutXAxisAnchor, + multiplier m: CGFloat, + constant c: CGFloat = 0.0) -> NSLayoutConstraint { + let constraint = self.constraint(lessThanOrEqualTo: anchor, constant: c) + return constraint.with(multiplier: m) + } +} + +extension NSLayoutYAxisAnchor { + func constraint(equalTo anchor: NSLayoutYAxisAnchor, + multiplier m: CGFloat, + constant c: CGFloat = 0.0) -> NSLayoutConstraint { + let constraint = self.constraint(equalTo: anchor, constant: c) + return constraint.with(multiplier: m) + } + + func constraint(greaterThanOrEqualTo anchor: NSLayoutYAxisAnchor, + multiplier m: CGFloat, + constant c: CGFloat = 0.0) -> NSLayoutConstraint { + let constraint = self.constraint(greaterThanOrEqualTo: anchor, constant: c) + return constraint.with(multiplier: m) + } + + func constraint(lessThanOrEqualTo anchor: NSLayoutYAxisAnchor, + multiplier m: CGFloat, + constant c: CGFloat = 0.0) -> NSLayoutConstraint { + let constraint = self.constraint(lessThanOrEqualTo: anchor, constant: c) + return constraint.with(multiplier: m) + } +} + +private extension NSLayoutConstraint { + func with(multiplier: CGFloat) -> NSLayoutConstraint { + return NSLayoutConstraint(item: firstItem!, + attribute: firstAttribute, + relatedBy: relation, + toItem: secondItem, + attribute: secondAttribute, + multiplier: multiplier, + constant: constant) + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Priority.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Priority.swift new file mode 100644 index 0000000..400976d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Anchorage/Source/Priority.swift @@ -0,0 +1,89 @@ +// +// Priority.swift +// Anchorage +// +// Created by Rob Visentin on 5/1/17. +// +// Copyright 2016 Raizlabs and other contributors +// http://raizlabs.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#if os(macOS) + import Cocoa +#else + import UIKit +#endif + +public enum Priority: ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral, Equatable { + + case required + case high + case low + case fittingSize + case custom(LayoutPriority) + + public var value: LayoutPriority { + switch self { + case .required: return LayoutPriorityRequired + case .high: return LayoutPriorityHigh + case .low: return LayoutPriorityLow + case .fittingSize: return LayoutPriorityFittingSize + case .custom(let priority): return priority + } + } + + public init(floatLiteral value: Float) { + self = .custom(LayoutPriority(value)) + } + + public init(integerLiteral value: Int) { + self.init(value) + } + + public init(_ value: Int) { + self = .custom(LayoutPriority(Float(value))) + } + + public init(_ value: T) { + self = .custom(LayoutPriority(Float(value))) + } + +} + +public func == (lhs: Priority, rhs: Priority) -> Bool { + return lhs.value == rhs.value +} + +public func + (lhs: Priority, rhs: T) -> Priority { + return .custom(LayoutPriority(rawValue: lhs.value.rawValue + Float(rhs))) +} + +public func + (lhs: T, rhs: Priority) -> Priority { + return .custom(LayoutPriority(rawValue: Float(lhs) + rhs.value.rawValue)) +} + +public func - (lhs: Priority, rhs: T) -> Priority { + return .custom(LayoutPriority(rawValue: lhs.value.rawValue - Float(rhs))) +} + +public func - (lhs: T, rhs: Priority) -> Priority { + return .custom(LayoutPriority(rawValue: Float(lhs) - rhs.value.rawValue)) +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/AppCenter b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/AppCenter new file mode 100644 index 0000000..2b390cd Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/AppCenter differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/AppCenter.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/AppCenter.h new file mode 100644 index 0000000..d26bd4d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/AppCenter.h @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSAbstractLog.h" +#import "MSAppCenter.h" +#import "MSAppCenterErrors.h" +#import "MSChannelGroupProtocol.h" +#import "MSChannelProtocol.h" +#import "MSConstants.h" +#import "MSCustomProperties.h" +#import "MSDevice.h" +#import "MSEnable.h" +#import "MSLog.h" +#import "MSLogWithProperties.h" +#import "MSLogger.h" +#import "MSService.h" +#import "MSServiceAbstract.h" +#import "MSUserInformation.h" +#import "MSWrapperLogger.h" +#import "MSWrapperSdk.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAbstractLog.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAbstractLog.h new file mode 100644 index 0000000..e90b7ff --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAbstractLog.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@interface MSAbstractLog : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenter.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenter.h new file mode 100644 index 0000000..39fd792 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenter.h @@ -0,0 +1,216 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSConstants.h" + +@class MSWrapperSdk; + +#if !TARGET_OS_TV +@class MSCustomProperties; +#endif + +@interface MSAppCenter : NSObject + +/** + * Returns the singleton instance of MSAppCenter. + */ ++ (instancetype)sharedInstance; + +/** + * Configure the SDK with an application secret. + * + * @param appSecret A unique and secret key used to identify the application. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)configureWithAppSecret:(NSString *)appSecret; + +/** + * Configure the SDK. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)configure; + +/** + * Configure the SDK with an application secret and an array of services to start. + * + * @param appSecret A unique and secret key used to identify the application. + * @param services Array of services to start. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)start:(NSString *)appSecret withServices:(NSArray *)services; + +/** + * Start the SDK with an array of services. + * + * @param services Array of services to start. + * + * @discussion This may be called only once per application process lifetime. + */ ++ (void)startWithServices:(NSArray *)services; + +/** + * Start a service. + * + * @param service A service to start. + * + * @discussion This may be called only once per service per application process lifetime. + */ ++ (void)startService:(Class)service; + +/** + * Configure the SDK with an array of services to start from a library. This will not start the service at application level, it will enable + * the service only for the library. + * + * @param services Array of services to start. + */ ++ (void)startFromLibraryWithServices:(NSArray *)services; + +/** + * Check whether the SDK has already been configured or not. + * + * @return YES if configured, NO otherwise. + */ ++ (BOOL)isConfigured; + +/** + * Change the base URL (schema + authority + port only) used to communicate with the backend. + * + * @param logUrl Base URL to use for backend communication. + */ ++ (void)setLogUrl:(NSString *)logUrl; + +/** + * Enable or disable the SDK as a whole. In addition to AppCenter resources, it will also enable or disable all registered services. + * The state is persisted in the device's storage across application launches. + * + * @param isEnabled YES to enable, NO to disable. + * + * @see isEnabled + */ ++ (void)setEnabled:(BOOL)isEnabled; + +/** + * Check whether the SDK is enabled or not as a whole. + * + * @return YES if enabled, NO otherwise. + * + * @see setEnabled: + */ ++ (BOOL)isEnabled; + +/** + * Get log level. + * + * @return Log level. + */ ++ (MSLogLevel)logLevel; + +/** + * Set log level. + * + * @param logLevel The log level. + */ ++ (void)setLogLevel:(MSLogLevel)logLevel; + +/** + * Set log level handler. + * + * @param logHandler Handler. + */ ++ (void)setLogHandler:(MSLogHandler)logHandler; + +/** + * Set wrapper SDK information to use when building device properties. This is intended in case you are building a SDK that uses the App + * Center SDK under the hood, e.g. our Xamarin SDK or ReactNative SDk. + * + * @param wrapperSdk Wrapper SDK information. + */ ++ (void)setWrapperSdk:(MSWrapperSdk *)wrapperSdk; + +#if !TARGET_OS_TV +/** + * Set the custom properties. + * + * @param customProperties Custom properties object. + */ ++ (void)setCustomProperties:(MSCustomProperties *)customProperties; +#endif + +/** + * Check whether the application delegate forwarder is enabled or not. + * + * @return YES if enabled, NO otherwise. + * + * @discussion The application delegate forwarder forwards messages that target your application delegate methods via swizzling to the SDK. + * It simplifies the SDK integration but may not be suitable to any situations. For + * instance it should be disabled if you or one of your third party SDK is doing message forwarding on the application delegate. Message + * forwarding usually implies the implementation of @see NSObject#forwardingTargetForSelector: or @see NSObject#forwardInvocation: methods. + * To disable the application delegate forwarder just add the `AppCenterAppDelegateForwarderEnabled` tag to your Info .plist file and set it + * to `0`. Then you will have to forward any application delegate needed by the SDK manually. + */ ++ (BOOL)isAppDelegateForwarderEnabled; + +/** + * Get unique installation identifier. + * + * @return Unique installation identifier. + */ ++ (NSUUID *)installId; + +/** + * Detect if a debugger is attached to the app process. This is only invoked once on app startup and can not detect + * if the debugger is being attached during runtime! + * + * @return BOOL if the debugger is attached. + */ ++ (BOOL)isDebuggerAttached; + +/** + * Get the current version of AppCenter SDK. + * + * @return The current version of AppCenter SDK. + */ ++ (NSString *)sdkVersion; + +/** + * Set the maximum size of the internal storage. This method must be called before App Center is started. This method is only intended for + * applications. + * + * @param sizeInBytes Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size + * (default is 4096 bytes). Values below 20,480 bytes (20 KiB) will be ignored. + * + * @param completionHandler Callback that is invoked when the database size has been set. The `BOOL` parameter is `YES` if changing the size + * is successful, and `NO` otherwise. This parameter can be null. + * + * @discussion This only sets the maximum size of the database, but App Center modules might store additional data. + * The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + */ ++ (void)setMaxStorageSize:(long)sizeInBytes completionHandler:(void (^)(BOOL))completionHandler; + +/** + * Set the user identifier. + * + * @param userId User identifier. + * + * @discussion Set the user identifier for logs sent for the default target token when the secret passed in @c + * MSAppCenter:start:withServices: contains "target={targetToken}". + * + * For App Center backend the user identifier maximum length is 256 characters. + * + * AppCenter must be configured or started before this API can be used. + */ ++ (void)setUserId:(NSString *)userId; + +/** + * Set country code to use when building device properties. + * + * @param countryCode The two-letter ISO country code. @see https://www.iso.org/obp/ui/#search for more information. + */ ++ (void)setCountryCode:(NSString *)countryCode; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenterErrors.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenterErrors.h new file mode 100644 index 0000000..a29c7aa --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSAppCenterErrors.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#define MS_APP_CENTER_BASE_DOMAIN @"com.Microsoft.AppCenter." + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Domain + +static NSString *const kMSACErrorDomain = MS_APP_CENTER_BASE_DOMAIN @"ErrorDomain"; + +#pragma mark - General + +// Error codes. +NS_ENUM(NSInteger){MSACLogInvalidContainerErrorCode = 1, MSACCanceledErrorCode = 2, MSACDisabledErrorCode = 3}; + +// Error descriptions. +static NSString const *kMSACLogInvalidContainerErrorDesc = @"Invalid log container."; +static NSString const *kMSACCanceledErrorDesc = @"The operation was canceled."; +static NSString const *kMSACDisabledErrorDesc = @"The service is disabled."; + +#pragma mark - Connection + +// Error codes. +NS_ENUM(NSInteger){MSACConnectionPausedErrorCode = 100, MSACConnectionHttpErrorCode = 101}; + +// Error descriptions. +static NSString const *kMSACConnectionHttpErrorDesc = @"An HTTP error occured."; +static NSString const *kMSACConnectionPausedErrorDesc = @"Canceled, connection paused with log deletion."; + +// Error user info keys. +static NSString const *kMSACConnectionHttpCodeErrorKey = @"MSACConnectionHttpCode"; + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelGroupProtocol.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelGroupProtocol.h new file mode 100644 index 0000000..8b0aa95 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelGroupProtocol.h @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSChannelProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@class MSChannelUnitConfiguration; + +@protocol MSIngestionProtocol; +@protocol MSChannelUnitProtocol; + +/** + * `MSChannelGroupProtocol` represents a kind of channel that contains constituent MSChannelUnit objects. When an operation from the + * `MSChannelProtocol` is performed on the group, that operation should be propagated to its constituent MSChannelUnit objects. + */ +@protocol MSChannelGroupProtocol + +/** + * Initialize a channel unit with the given configuration. + * + * @param configuration channel configuration. + * + * @return The added `MSChannelUnitProtocol`. Use this object to enqueue logs. + */ +- (id)addChannelUnitWithConfiguration:(MSChannelUnitConfiguration *)configuration; + +/** + * Initialize a channel unit with the given configuration. + * + * @param configuration channel configuration. + * @param ingestion The alternative ingestion object + * + * @return The added `MSChannelUnitProtocol`. Use this object to enqueue logs. + */ +- (id)addChannelUnitWithConfiguration:(MSChannelUnitConfiguration *)configuration + withIngestion:(nullable id)ingestion; + +/** + * Change the base URL (schema + authority + port only) used to communicate with the backend. + * + * @param logUrl base URL to use for backend communication. + */ +- (void)setLogUrl:(NSString *)logUrl; + +/** + * Set the app secret. + * + * @param appSecret The app secret. + */ +- (void)setAppSecret:(NSString *)appSecret; + +/** + * Set the maximum size of the internal storage. This method must be called before App Center is started. + * + * @discussion The default maximum database size is 10485760 bytes (10 MiB). + * + * @param sizeInBytes Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size + * (default is 4096 bytes). Values below 24576 bytes (24 KiB) will be ignored. + * @param completionHandler Callback that is invoked when the database size has been set. The `BOOL` parameter is `YES` if changing the size + * is successful, and `NO` otherwise. + */ +- (void)setMaxStorageSize:(long)sizeInBytes completionHandler:(nullable void (^)(BOOL))completionHandler; + +/** + * Return a channel unit instance for the given groupId. + * + * @param groupId The group ID for a channel unit. + * + * @return A channel unit instance or `nil`. + */ +- (id)channelUnitForGroupId:(NSString *)groupId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelProtocol.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelProtocol.h new file mode 100644 index 0000000..5198b86 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSChannelProtocol.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSEnable.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol MSChannelDelegate; + +/** + * `MSChannelProtocol` contains the essential operations of a channel. Channels are broadly responsible for enqueuing logs to be sent to the + * backend and/or stored on disk. + */ +@protocol MSChannelProtocol + +/** + * Add delegate. + * + * @param delegate delegate. + */ +- (void)addDelegate:(id)delegate; + +/** + * Remove delegate. + * + * @param delegate delegate. + */ +- (void)removeDelegate:(id)delegate; + +/** + * Pause operations, logs will be stored but not sent. + * + * @param identifyingObject Object used to identify the pause request. + * + * @discussion A paused channel doesn't forward logs to the ingestion. The identifying object used to pause the channel can be any unique + * object. The same identifying object must be used to call resume. For simplicity if the caller is the one owning the channel then @c self + * can be used as identifying object. + * + * @see resumeWithIdentifyingObject: + */ +- (void)pauseWithIdentifyingObject:(id)identifyingObject; + +/** + * Resume operations, logs can be sent again. + * + * @param identifyingObject Object used to passed to the pause method. + * + * @discussion The channel only resume when all the outstanding identifying objects have been resumed. + * + * @see pauseWithIdentifyingObject: + */ +- (void)resumeWithIdentifyingObject:(id)identifyingObject; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSConstants.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSConstants.h new file mode 100644 index 0000000..047c9f7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSConstants.h @@ -0,0 +1,170 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Log Levels + */ +typedef NS_ENUM(NSUInteger, MSLogLevel) { + + /** + * Logging will be very chatty + */ + MSLogLevelVerbose = 2, + + /** + * Debug information will be logged + */ + MSLogLevelDebug = 3, + + /** + * Information will be logged + */ + MSLogLevelInfo = 4, + + /** + * Errors and warnings will be logged + */ + MSLogLevelWarning = 5, + + /** + * Errors will be logged + */ + MSLogLevelError = 6, + + /** + * Only critical errors will be logged + */ + MSLogLevelAssert = 7, + + /** + * Logging is disabled + */ + MSLogLevelNone = 99 +}; + +typedef NSString * (^MSLogMessageProvider)(void); +typedef void (^MSLogHandler)(MSLogMessageProvider messageProvider, MSLogLevel logLevel, NSString *tag, const char *file, + const char *function, uint line); + +/** + * Channel priorities, check the kMSPriorityCount if you add a new value. + * The order matters here! Values NEED to range from low priority to high priority. + */ +typedef NS_ENUM(NSInteger, MSPriority) { MSPriorityBackground, MSPriorityDefault, MSPriorityHigh }; +static short const kMSPriorityCount = MSPriorityHigh + 1; + +/** + * The priority by which the modules are initialized. + * MSPriorityMax is reserved for only 1 module and this needs to be Crashes. + * Crashes needs to be initialized first to catch crashes in our other SDK Modules (which will hopefully never happen) and to avoid losing + * any log at crash time. + */ +typedef NS_ENUM(NSInteger, MSInitializationPriority) { + MSInitializationPriorityDefault = 500, + MSInitializationPriorityHigh = 750, + MSInitializationPriorityMax = 999 +}; + +/** + * Enum with the different HTTP status codes. + */ +typedef NS_ENUM(NSInteger, MSHTTPCodesNo) { + + // Invalid + MSHTTPCodesNo0XXInvalidUnknown = 0, + + // Informational + MSHTTPCodesNo1XXInformationalUnknown = 1, + MSHTTPCodesNo100Continue = 100, + MSHTTPCodesNo101SwitchingProtocols = 101, + MSHTTPCodesNo102Processing = 102, + + // Success + MSHTTPCodesNo2XXSuccessUnknown = 2, + MSHTTPCodesNo200OK = 200, + MSHTTPCodesNo201Created = 201, + MSHTTPCodesNo202Accepted = 202, + MSHTTPCodesNo203NonAuthoritativeInformation = 203, + MSHTTPCodesNo204NoContent = 204, + MSHTTPCodesNo205ResetContent = 205, + MSHTTPCodesNo206PartialContent = 206, + MSHTTPCodesNo207MultiStatus = 207, + MSHTTPCodesNo208AlreadyReported = 208, + MSHTTPCodesNo209IMUsed = 209, + + // Redirection + MSHTTPCodesNo3XXSuccessUnknown = 3, + MSHTTPCodesNo300MultipleChoices = 300, + MSHTTPCodesNo301MovedPermanently = 301, + MSHTTPCodesNo302Found = 302, + MSHTTPCodesNo303SeeOther = 303, + MSHTTPCodesNo304NotModified = 304, + MSHTTPCodesNo305UseProxy = 305, + MSHTTPCodesNo306SwitchProxy = 306, + MSHTTPCodesNo307TemporaryRedirect = 307, + MSHTTPCodesNo308PermanentRedirect = 308, + + // Client error + MSHTTPCodesNo4XXSuccessUnknown = 4, + MSHTTPCodesNo400BadRequest = 400, + MSHTTPCodesNo401Unauthorised = 401, + MSHTTPCodesNo402PaymentRequired = 402, + MSHTTPCodesNo403Forbidden = 403, + MSHTTPCodesNo404NotFound = 404, + MSHTTPCodesNo405MethodNotAllowed = 405, + MSHTTPCodesNo406NotAcceptable = 406, + MSHTTPCodesNo407ProxyAuthenticationRequired = 407, + MSHTTPCodesNo408RequestTimeout = 408, + MSHTTPCodesNo409Conflict = 409, + MSHTTPCodesNo410Gone = 410, + MSHTTPCodesNo411LengthRequired = 411, + MSHTTPCodesNo412PreconditionFailed = 412, + MSHTTPCodesNo413RequestEntityTooLarge = 413, + MSHTTPCodesNo414RequestURITooLong = 414, + MSHTTPCodesNo415UnsupportedMediaType = 415, + MSHTTPCodesNo416RequestedRangeNotSatisfiable = 416, + MSHTTPCodesNo417ExpectationFailed = 417, + MSHTTPCodesNo418IamATeapot = 418, + MSHTTPCodesNo419AuthenticationTimeout = 419, + MSHTTPCodesNo420MethodFailureSpringFramework = 420, + MSHTTPCodesNo420EnhanceYourCalmTwitter = 4200, + MSHTTPCodesNo422UnprocessableEntity = 422, + MSHTTPCodesNo423Locked = 423, + MSHTTPCodesNo424FailedDependency = 424, + MSHTTPCodesNo424MethodFailureWebDaw = 4240, + MSHTTPCodesNo425UnorderedCollection = 425, + MSHTTPCodesNo426UpgradeRequired = 426, + MSHTTPCodesNo428PreconditionRequired = 428, + MSHTTPCodesNo429TooManyRequests = 429, + MSHTTPCodesNo431RequestHeaderFieldsTooLarge = 431, + MSHTTPCodesNo444NoResponseNginx = 444, + MSHTTPCodesNo449RetryWithMicrosoft = 449, + MSHTTPCodesNo450BlockedByWindowsParentalControls = 450, + MSHTTPCodesNo451RedirectMicrosoft = 451, + MSHTTPCodesNo451UnavailableForLegalReasons = 4510, + MSHTTPCodesNo494RequestHeaderTooLargeNginx = 494, + MSHTTPCodesNo495CertErrorNginx = 495, + MSHTTPCodesNo496NoCertNginx = 496, + MSHTTPCodesNo497HTTPToHTTPSNginx = 497, + MSHTTPCodesNo499ClientClosedRequestNginx = 499, + + // Server error + MSHTTPCodesNo5XXSuccessUnknown = 5, + MSHTTPCodesNo500InternalServerError = 500, + MSHTTPCodesNo501NotImplemented = 501, + MSHTTPCodesNo502BadGateway = 502, + MSHTTPCodesNo503ServiceUnavailable = 503, + MSHTTPCodesNo504GatewayTimeout = 504, + MSHTTPCodesNo505HTTPVersionNotSupported = 505, + MSHTTPCodesNo506VariantAlsoNegotiates = 506, + MSHTTPCodesNo507InsufficientStorage = 507, + MSHTTPCodesNo508LoopDetected = 508, + MSHTTPCodesNo509BandwidthLimitExceeded = 509, + MSHTTPCodesNo510NotExtended = 510, + MSHTTPCodesNo511NetworkAuthenticationRequired = 511, + MSHTTPCodesNo522ConnectionTimedOut = 522, + MSHTTPCodesNo598NetworkReadTimeoutErrorUnknown = 598, + MSHTTPCodesNo599NetworkConnectTimeoutErrorUnknown = 599 +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSCustomProperties.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSCustomProperties.h new file mode 100644 index 0000000..17e4a2a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSCustomProperties.h @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Custom properties builder. + * Collects multiple properties to send in one log. + */ +@interface MSCustomProperties : NSObject + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setString:(NSString *)value forKey:(NSString *)key; + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setNumber:(NSNumber *)value forKey:(NSString *)key; + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setBool:(BOOL)value forKey:(NSString *)key; + +/** + * Set the specified property value with the specified key. + * If the properties previously contained a property for the key, the old value is replaced. + * + * @param key Key with which the specified value is to be set. + * @param value Value to be set with the specified key. + * + * @return This instance. + */ +- (instancetype)setDate:(NSDate *)value forKey:(NSString *)key; + +/** + * Clear the property for the specified key. + * + * @param key Key whose mapping is to be cleared. + * + * @return This instance. + */ +- (instancetype)clearPropertyForKey:(NSString *)key; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSDevice.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSDevice.h new file mode 100644 index 0000000..587a22a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSDevice.h @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSWrapperSdk.h" + +@interface MSDevice : MSWrapperSdk + +/* + * Name of the SDK. Consists of the name of the SDK and the platform, e.g. "appcenter.ios", "appcenter.android" + */ +@property(nonatomic, copy, readonly) NSString *sdkName; + +/* + * Version of the SDK in semver format, e.g. "1.2.0" or "0.12.3-alpha.1". + */ +@property(nonatomic, copy, readonly) NSString *sdkVersion; + +/* + * Device model (example: iPad2,3). + */ +@property(nonatomic, copy, readonly) NSString *model; + +/* + * Device manufacturer (example: HTC). + */ +@property(nonatomic, copy, readonly) NSString *oemName; + +/* + * OS name (example: iOS). + */ +@property(nonatomic, copy, readonly) NSString *osName; + +/* + * OS version (example: 9.3.0). + */ +@property(nonatomic, copy, readonly) NSString *osVersion; + +/* + * OS build code (example: LMY47X). [optional] + */ +@property(nonatomic, copy, readonly) NSString *osBuild; + +/* + * API level when applicable like in Android (example: 15). [optional] + */ +@property(nonatomic, copy, readonly) NSNumber *osApiLevel; + +/* + * Language code (example: en_US). + */ +@property(nonatomic, copy, readonly) NSString *locale; + +/* + * The offset in minutes from UTC for the device time zone, including daylight savings time. + */ +@property(nonatomic, readonly) NSNumber *timeZoneOffset; + +/* + * Screen size of the device in pixels (example: 640x480). + */ +@property(nonatomic, copy, readonly) NSString *screenSize; + +/* + * Application version name, e.g. 1.1.0 + */ +@property(nonatomic, copy, readonly) NSString *appVersion; + +/* + * Carrier name (for mobile devices). [optional] + */ +@property(nonatomic, copy, readonly) NSString *carrierName; + +/* + * Carrier country code (for mobile devices). [optional] + */ +@property(nonatomic, copy, readonly) NSString *carrierCountry; + +/* + * The app's build number, e.g. 42. + */ +@property(nonatomic, copy, readonly) NSString *appBuild; + +/* + * The bundle identifier, package identifier, or namespace, depending on what the individual plattforms use, .e.g com.microsoft.example. + * [optional] + */ +@property(nonatomic, copy, readonly) NSString *appNamespace; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSEnable.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSEnable.h new file mode 100644 index 0000000..e092b1a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSEnable.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Protocol to define an instance that can be enabled/disabled. + */ +@protocol MSEnable + +@required + +/** + * Enable/disable this instance and delete data on disabled state. + * + * @param isEnabled A boolean value set to YES to enable the instance or NO to disable it. + * @param deleteData A boolean value set to YES to delete data or NO to keep it. + */ +- (void)setEnabled:(BOOL)isEnabled andDeleteDataOnDisabled:(BOOL)deleteData; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLog.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLog.h new file mode 100644 index 0000000..d62aa62 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLog.h @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@class MSDevice; + +@protocol MSLog + +/** + * Log type. + */ +@property(nonatomic, copy) NSString *type; + +/** + * Log timestamp. + */ +@property(nonatomic) NSDate *timestamp; + +/** + * A session identifier is used to correlate logs together. A session is an abstract concept in the API and is not necessarily an analytics + * session, it can be used to only track crashes. + */ +@property(nonatomic, copy) NSString *sid; + +/** + * Optional distribution group ID value. + */ +@property(nonatomic, copy) NSString *distributionGroupId; + +/** + * Optional user identifier. + */ +@property(nonatomic, copy) NSString *userId; + +/** + * Device properties associated to this log. + */ +@property(nonatomic) MSDevice *device; + +/** + * Transient object tag. For example, a log can be tagged with a transmission target. We do this currently to prevent properties being + * applied retroactively to previous logs by comparing their tags. + */ +@property(nonatomic) NSObject *tag; + +/** + * Checks if the object's values are valid. + * + * @return YES, if the object is valid. + */ +- (BOOL)isValid; + +/** + * Adds a transmission target token that this log should be sent to. + * + * @param token The transmission target token. + */ +- (void)addTransmissionTargetToken:(NSString *)token; + +/** + * Gets all transmission target tokens that this log should be sent to. + * + * @returns Collection of transmission target tokens that this log should be sent to. + */ +- (NSSet *)transmissionTargetTokens; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogWithProperties.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogWithProperties.h new file mode 100644 index 0000000..f9fdd5c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogWithProperties.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSAbstractLog.h" + +@interface MSLogWithProperties : MSAbstractLog + +/** + * Additional key/value pair parameters. [optional] + */ +@property(nonatomic) NSDictionary *properties; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogger.h new file mode 100644 index 0000000..7eb5c3b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSLogger.h @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSConstants.h" + +#define MSLog(_level, _tag, _message) \ + [MSLogger logMessage:_message level:_level tag:_tag file:__FILE__ function:__PRETTY_FUNCTION__ line:__LINE__] +#define MSLogAssert(tag, format, ...) \ + MSLog(MSLogLevelAssert, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogError(tag, format, ...) \ + MSLog(MSLogLevelError, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogWarning(tag, format, ...) \ + MSLog(MSLogLevelWarning, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogInfo(tag, format, ...) \ + MSLog(MSLogLevelInfo, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogDebug(tag, format, ...) \ + MSLog(MSLogLevelDebug, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) +#define MSLogVerbose(tag, format, ...) \ + MSLog(MSLogLevelVerbose, tag, (^{ \ + return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ + })) + +@interface MSLogger : NSObject + ++ (void)logMessage:(MSLogMessageProvider)messageProvider + level:(MSLogLevel)loglevel + tag:(NSString *)tag + file:(const char *)file + function:(const char *)function + line:(uint)line; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSService.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSService.h new file mode 100644 index 0000000..72c929d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSService.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Protocol declaring service logic. + */ +@protocol MSService + +/** + * Enable or disable this service. + * The state is persisted in the device's storage across application launches. + * + * @param isEnabled Whether this service is enabled or not. + * + * @see isEnabled + */ ++ (void)setEnabled:(BOOL)isEnabled; + +/** + * Indicates whether this service is enabled. + * + * @return `YES` if this service is enabled, `NO` if it is not. + * + * @see setEnabled: + */ ++ (BOOL)isEnabled; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSServiceAbstract.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSServiceAbstract.h new file mode 100644 index 0000000..d51e1e1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSServiceAbstract.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSService.h" + +@protocol MSChannelGroupProtocol; + +/** + * Abstraction of services common logic. + * This class is intended to be subclassed only not instantiated directly. + */ +@interface MSServiceAbstract : NSObject + +/** + * The flag indicates whether the service is started from application or not. + */ +@property(nonatomic) BOOL startedFromApplication; + +/** + * Start this service with a channel group. Also sets the flag that indicates that a service has been started. + * + * @param channelGroup channel group used to persist and send logs. + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + * @param fromApplication indicates whether the service started from an application or not. + */ +- (void)startWithChannelGroup:(id)channelGroup + appSecret:(NSString *)appSecret + transmissionTargetToken:(NSString *)token + fromApplication:(BOOL)fromApplication; + +/** + * Update configuration when the service requires to start again. This method should only be called if the service is started from libraries + * and then is being started from an application. + * + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + */ +- (void)updateConfigurationWithAppSecret:(NSString *)appSecret transmissionTargetToken:(NSString *)token; + +/** + * Checks if the service needs the application secret. + * + * @return `YES` if the application secret is required, `NO` otherwise. + */ +- (BOOL)isAppSecretRequired; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSUserInformation.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSUserInformation.h new file mode 100644 index 0000000..8f8b7c6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSUserInformation.h @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MSUserInformation : NSObject + +/** + * The account identifier for the user. + */ +@property(nonatomic, copy) NSString *accountId; + +/** + * Create user with account identifier. + * + * @param accountId account identifier for the user. + * + * @return user with account identifier. + */ +- (instancetype)initWithAccountId:(NSString *)accountId; +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperLogger.h new file mode 100644 index 0000000..1e17ff1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperLogger.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSConstants.h" + +/** + * This is a utility for producing App Center style log messages. It is only intended for use by App Center services and wrapper SDKs of App + * Center. + */ +@interface MSWrapperLogger : NSObject + ++ (void)MSWrapperLog:(MSLogMessageProvider)message tag:(NSString *)tag level:(MSLogLevel)level; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperSdk.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperSdk.h new file mode 100644 index 0000000..29b5a58 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Headers/MSWrapperSdk.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@interface MSWrapperSdk : NSObject + +/* + * Version of the wrapper SDK. When the SDK is embedding another base SDK (for example Xamarin.Android wraps Android), the Xamarin specific + * version is populated into this field while sdkVersion refers to the original Android SDK. [optional] + */ +@property(nonatomic, copy, readonly) NSString *wrapperSdkVersion; + +/* + * Name of the wrapper SDK (examples: Xamarin, Cordova). [optional] + */ +@property(nonatomic, copy, readonly) NSString *wrapperSdkName; + +/* + * Version of the wrapper technology framework (Xamarin runtime version or ReactNative or Cordova etc...). [optional] + */ +@property(nonatomic, copy, readonly) NSString *wrapperRuntimeVersion; + +/* + * Label that is used to identify application code 'version' released via Live Update beacon running on device. + */ +@property(nonatomic, copy, readonly) NSString *liveUpdateReleaseLabel; + +/* + * Identifier of environment that current application release belongs to, deployment key then maps to environment like Production, Staging. + */ +@property(nonatomic, copy, readonly) NSString *liveUpdateDeploymentKey; + +/* + * Hash of all files (ReactNative or Cordova) deployed to device via LiveUpdate beacon. Helps identify the Release version on device or need + * to download updates in future + */ +@property(nonatomic, copy, readonly) NSString *liveUpdatePackageHash; + +- (instancetype)initWithWrapperSdkVersion:(NSString *)wrapperSdkVersion + wrapperSdkName:(NSString *)wrapperSdkName + wrapperRuntimeVersion:(NSString *)wrapperRuntimeVersion + liveUpdateReleaseLabel:(NSString *)liveUpdateReleaseLabel + liveUpdateDeploymentKey:(NSString *)liveUpdateDeploymentKey + liveUpdatePackageHash:(NSString *)liveUpdatePackageHash; + +/** + * Checks if the object's values are valid. + * + * @return YES, if the object is valid. + */ +- (BOOL)isValid; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Modules/module.modulemap new file mode 100644 index 0000000..f15d734 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenter.framework/Modules/module.modulemap @@ -0,0 +1,13 @@ +framework module AppCenter { + umbrella header "AppCenter.h" + + export * + module * { export * } + + link framework "Foundation" + link framework "CoreTelephony" + link framework "SystemConfiguration" + link framework "UIKit" + link "sqlite3" + link "z" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/AppCenterDistribute b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/AppCenterDistribute new file mode 100644 index 0000000..1c5934e Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/AppCenterDistribute differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/AppCenterDistribute.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/AppCenterDistribute.h new file mode 100644 index 0000000..8cf0eef --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/AppCenterDistribute.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSDistribute.h" +#import "MSDistributeDelegate.h" +#import "MSReleaseDetails.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistribute.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistribute.h new file mode 100644 index 0000000..4b06f12 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistribute.h @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import "MSDistributeDelegate.h" +#import "MSServiceAbstract.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * App Center Distribute service. + */ +@interface MSDistribute : MSServiceAbstract + +/** + * Set a Distribute delegate + * + * @param delegate A Distribute delegate. + * + * @discussion If Distribute delegate is set and releaseAvailableWithDetails is returning YES, you must call + * notifyUpdateAction: with one of update actions to handle a release properly. + * + * @see releaseAvailableWithDetails: + * @see notifyUpdateAction: + */ ++ (void)setDelegate:(id)delegate; + +/** + * Notify SDK with an update action to handle the release. + */ ++ (void)notifyUpdateAction:(MSUpdateAction)action; + +/** + * Change The URL that will be used for generic update related tasks. + * + * @param apiUrl The new URL. + */ ++ (void)setApiUrl:(NSString *)apiUrl; + +/** + * Change the base URL that is used to install update. + * + * @param installUrl The new URL. + */ ++ (void)setInstallUrl:(NSString *)installUrl; + +/** + * Process URL request for the service. + * + * @param url The url with parameters. + * + * @return `YES` if the URL is intended for App Center Distribute and your application, `NO` otherwise. + * + * @discussion Place this method call into your app delegate's openURL method. + */ ++ (BOOL)openURL:(NSURL *)url; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistributeDelegate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistributeDelegate.h new file mode 100644 index 0000000..f9c34c3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSDistributeDelegate.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import "MSReleaseDetails.h" + +@class MSDistribute; + +@protocol MSDistributeDelegate + +typedef NS_ENUM(NSInteger, MSUpdateAction) { + + /** + * Action to trigger update. + */ + MSUpdateActionUpdate, + + /** + * Action to postpone update. + */ + MSUpdateActionPostpone +}; + +@optional + +/** + * Callback method that will be called whenever a new release is available for update. + * + * @param distribute The instance of MSDistribute. + * @param details Release details for the update. + * + * @return Return YES if you want to take update control by overriding default update dialog, NO otherwise. + * + * @see [MSDistribute notifyUpdateAction:] + */ +- (BOOL)distribute:(MSDistribute *)distribute releaseAvailableWithDetails:(MSReleaseDetails *)details; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSReleaseDetails.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSReleaseDetails.h new file mode 100644 index 0000000..a5c1238 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSReleaseDetails.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +@class MSDistributionGroup; + +/** + * Details of an uploaded release. + */ +@interface MSReleaseDetails : NSObject + +/** + * ID identifying this unique release. + */ +@property(nonatomic, copy) NSNumber *id; + +/** + * The release's version + * For iOS: CFBundleVersion from info.plist + * For Android: android:versionCode from AndroidManifest.xml + */ +@property(nonatomic, copy) NSString *version; + +/** + * The release's short version. + * For iOS: CFBundleShortVersionString from info.plist + * For Android: android:versionName from AndroidManifest.xml + */ +@property(nonatomic, copy) NSString *shortVersion; + +/** + * The release's release notes. + */ +@property(nonatomic, copy) NSString *releaseNotes; + +/** + * The flag that indicates whether the release is a mandatory update or not. + */ +@property(nonatomic) BOOL mandatoryUpdate; + +/** + * The URL that hosts the release notes for this release. + */ +@property(nonatomic) NSURL *releaseNotesUrl; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSService.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSService.h new file mode 100644 index 0000000..72c929d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSService.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +/** + * Protocol declaring service logic. + */ +@protocol MSService + +/** + * Enable or disable this service. + * The state is persisted in the device's storage across application launches. + * + * @param isEnabled Whether this service is enabled or not. + * + * @see isEnabled + */ ++ (void)setEnabled:(BOOL)isEnabled; + +/** + * Indicates whether this service is enabled. + * + * @return `YES` if this service is enabled, `NO` if it is not. + * + * @see setEnabled: + */ ++ (BOOL)isEnabled; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSServiceAbstract.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSServiceAbstract.h new file mode 100644 index 0000000..d51e1e1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Headers/MSServiceAbstract.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "MSService.h" + +@protocol MSChannelGroupProtocol; + +/** + * Abstraction of services common logic. + * This class is intended to be subclassed only not instantiated directly. + */ +@interface MSServiceAbstract : NSObject + +/** + * The flag indicates whether the service is started from application or not. + */ +@property(nonatomic) BOOL startedFromApplication; + +/** + * Start this service with a channel group. Also sets the flag that indicates that a service has been started. + * + * @param channelGroup channel group used to persist and send logs. + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + * @param fromApplication indicates whether the service started from an application or not. + */ +- (void)startWithChannelGroup:(id)channelGroup + appSecret:(NSString *)appSecret + transmissionTargetToken:(NSString *)token + fromApplication:(BOOL)fromApplication; + +/** + * Update configuration when the service requires to start again. This method should only be called if the service is started from libraries + * and then is being started from an application. + * + * @param appSecret app secret for the SDK. + * @param token default transmission target token for this service. + */ +- (void)updateConfigurationWithAppSecret:(NSString *)appSecret transmissionTargetToken:(NSString *)token; + +/** + * Checks if the service needs the application secret. + * + * @return `YES` if the application secret is required, `NO` otherwise. + */ +- (BOOL)isAppSecretRequired; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Modules/module.modulemap new file mode 100644 index 0000000..f89a286 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework/Modules/module.modulemap @@ -0,0 +1,10 @@ +framework module AppCenterDistribute { + umbrella header "AppCenterDistribute.h" + + export * + module * { export * } + + link framework "Foundation" + link framework "SafariServices" + link framework "UIKit" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..2693e0b Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..bc7d18b Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..61329ba Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..a0c78ce Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..71db5ab Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..9a1461d Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..2eb663a Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..7d35e54 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..04346ed Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..6341c8d Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..bfabe63 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..767f8ea Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..4f88c85 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj/AppCenterDistribute.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj/AppCenterDistribute.strings new file mode 100644 index 0000000..ff29885 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj/AppCenterDistribute.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/LICENSE new file mode 100644 index 0000000..6a66415 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/AppCenter/AppCenter-SDK-Apple/iOS/LICENSE @@ -0,0 +1,25 @@ +Visual Studio App Center SDK for Apple platforms + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/LICENSE new file mode 100644 index 0000000..7b9a500 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright © 2014 Raizlabs and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/README.md new file mode 100644 index 0000000..04d5886 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/README.md @@ -0,0 +1,380 @@ +BonMot Logo + +[![Swift 4.0](https://img.shields.io/badge/Swift-4.0-orange.svg?style=flat)](https://swift.org) +[![CircleCI](https://img.shields.io/circleci/project/github/Raizlabs/BonMot/master.svg)](https://circleci.com/gh/Raizlabs/BonMot) +[![Version](https://img.shields.io/cocoapods/v/BonMot.svg?style=flat)](http://cocoapods.org/pods/BonMot) +[![License](https://img.shields.io/cocoapods/l/BonMot.svg?style=flat)](http://cocoapods.org/pods/BonMot) +[![Platform](https://img.shields.io/cocoapods/p/BonMot.svg?style=flat)](http://cocoapods.org/pods/BonMot) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![codecov](https://codecov.io/gh/Raizlabs/BonMot/branch/master/graph/badge.svg)](https://codecov.io/gh/Raizlabs/BonMot) + +BonMot (pronounced *Bon Mo*, French for *good word*) is a Swift attributed string library. It abstracts away the complexities of the iOS, macOS, tvOS, and watchOS typography tools, freeing you to focus on making your text beautiful. + +To run the example project, run `pod try BonMot`, or clone the repo, open `BonMot.xcodeproj`, and run the **Example-iOS** target. + +### Note +If you are migrating a project from BonMot 3 to BonMot 4, please see the [Migration Guide](#bonmot-3--4-migration-guide). + +# Usage + +In any Swift file where you want to use BonMot, simply `import BonMot`. + +## Basics + +Use a `StringStyle` to specify the style of your attributed string. Then, use the `styled(with:)` method on `String` to get your attributed string: + +```swift +let quote = """ + I used to love correcting people’s grammar until \ + I realized what I loved more was having friends. + -Mara Wilson + """ + +let style = StringStyle( + .font(UIFont(name: "AmericanTypewriter", size: 17)!), + .lineHeightMultiple(1.8) +) + +let attributedString = quote.styled(with: style) + +// You can also get the style’s attributes dictionary +// if you’re using an API that requires it. +let attributes = style.attributes +``` + +### Glossary + +These are the types with which you will most commonly interact when using BonMot to build attributed strings. + +- `StringStyle`: a collection of attributes which can be used to style a string. These include basics, like font and color, and more advanced settings like paragraph controls and OpenType features. To get a good idea of the full set of features that BonMot supports, look at the interface for this struct. +- `StringStyle.Part`: an enum which can be used to concisely construct a `StringStyle`. You will typically interact with these, rather than constructing `StringStyle`s attribute by attribute. +- `Composable`: a protocol defining any type that knows how to append itself to an attributed string. BonMot provides functions, such as the one in [this example](#debugging--testing-helpers), to join together multiple `Composable` values. +- `NamedStyles`: use this to register custom, reusable styles in a global namespace. +- `Special`: a utility to include special, ambiguous, and non-printing characters in your strings without making your code unreadable. + +### Style Inheritance + +Styles can inherit from each other, which lets you create multiple styles that share common attributes: + +```swift +let baseStyle = StringStyle( + .lineHeightMultiple(1.2), + .font(UIFont.systemFont(ofSize: 17)) +) + +let redStyle = baseStyle.byAdding(.color(.red)) +let blueStyle = baseStyle.byAdding(.color(.blue)) + +let redBirdString = "bird".styled(with: redStyle) +let blueBirdString = "bird".styled(with: blueStyle) +``` + +### XML Parsing + +Are you trying to style just part of a string, perhaps even a localized string which is different depending on the locale of the app? No problem! BonMot can turn custom XML tags and simple HTML into attributed strings: + +```swift +// This would typically be a localized string +let string = "one fish, two fish, red fish,blue fish" + +let redStyle = StringStyle(.color(.red)) +let blueStyle = StringStyle(.color(.blue)) + +let fishStyle = StringStyle( + .font(UIFont.systemFont(ofSize: 17)), + .lineHeightMultiple(1.8), + .color(.darkGray), + .xmlRules([ + .style("red", redStyle), + .style("blue", blueStyle), + ]) +) + +let attributedString = string.styled(with: fishStyle) +``` + +This will produce: + + + +> Note the use of `` to specify a special character within the string. This is a great way to add special characters to localized strings, since localizers might not know to look for special characters, and many of them are invisible or ambiguous when viewed in a normal text editor. You can use any characters in the `Special` enum, or use `` or `&#a1338;` + +#### XML Parsing with Error Handling + +If the above method encounters invalid XML, the resulting string will be the entire original string, tags and all. If you are parsing XML that is out of your control, e.g. variable content from a server, you may want to use this alternate parsing mechanism, which allows you to handle errors encountered while parsing: + +```swift +let rules: [XMLStyleRule] = [ + .style("strong", strongStyle), + .style("em", emStyle), +] + +let xml = // some XML from a server + +do { + let attrString = try NSAttributedString.composed(ofXML: xml, rules: rules) +} +catch { + // Handle errors encountered by Foundation's XMLParser, + // which is used by BonMot to parse XML. +} +``` + +## Image Attachments + +BonMot uses `NSTextAttachment` to embed images in strings. You can use BonMot’s `NSAttributedString.composed(of:)` API to chain images and text together in the same string: + +```swift +let someImage = ... // some UIImage or NSImage + +let attributedString = NSAttributedString.composed(of: [ + someImage.styled(with: .baselineOffset(-4)), // shift vertically if needed + Special.noBreakSpace, // a non-breaking space between image and text + "label with icon", // raw or attributed string + ]) +``` + +> Note the use of the `Special` type, which gives you easy access to Unicode characters that are commonly used in UIs, such as spaces, dashes, and non-printing characters. + +Outputs: + + + +If you need to wrap multiple lines of text after an image, use `Tab.headIndent(...)` to align the whole paragraph after the image: + +```swift +let attributedString = NSAttributedString.composed(of: [ + someImage.styled(with: .baselineOffset(-4.0)), // shift vertically if needed + Tab.headIndent(10), // horizontal space between image and text + "This is some text that goes on and on and spans multiple lines, and it all ends up left-aligned", + ]) +``` + +Outputs: + + + +## Dynamic Type + +You can easily make any attributed string generated by BonMot respond to the system text size control. Simply add `.adapt` to any style declaration, and specify whether you want the style to scale like a `.control` or like `.body` text. + +```swift +let style = StringStyle( + .adapt(.control) + // other style parts can go here as needed +) + +someLabel.attributedText = "Label".styled(with: style).adapted(to: traitCollection) +``` + +If you want an attributed string to adapt to the current content size category, when setting it on a UI element, use `.adapted(to: traitCollection)` as in the above example. + +### Responding to Content Size Category Changes + +If you call `UIApplication.shared.enableAdaptiveContentSizeMonitor()` at some point in your app setup code, BonMot will update common UI elements as the preferred content size category changes. You can opt your custom controls into automatic updating by conforming them to the `AdaptableTextContainer` protocol. + +If you want more manual control over the adaptation process and are targeting iOS 10+, skip enabling the adaptive content size monitor, and call `.adapted(to: traitCollection)` inside `traitCollectionDidChange(_:)`. iOS 10 introduced a `preferredContentSizeCategory` property on `UITraitCollection`. + +### Scaling Behaviors + +The `.control` and `.body` behaviors both scale the same, except that when enabling the "Larger Dynamic Type" accessibility setting, `.body` grows unbounded. Here is a graph of the default behaviors of the [system Dynamic Type styles](https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography#dynamic-type-sizes): + +Graph of iOS Dynamic Type scaling behavior, showing that Control text tops out at the XXL size, but Body text keeps growing all the way up to AccessibilityXXL + +## Storyboard and XIB Integration + +You can register global named styles, and use them in Storyboards and XIBs via `IBInspectable`: + +```swift +let style = StringStyle( + .font(UIFont(name: "Avenir-Roman", size: 24)!), + .color(.red), + .underline(.styleSingle, .red) +) +NamedStyles.shared.registerStyle(forName: "MyHeadline", style: style) +``` + +You can then use `MyHeadline` in Interface Builder’s Attributes Inspector on common UIKit controls such as buttons and labels: + +Editing the Bon Mot Style Name attribute in the Attributes Inspector of Interface Builder, and setting the value to MyHeadline + +These same named styles will also be picked up if they are used as tag names in [parsed XML](s#xml-parsing). + +## Debugging & Testing Helpers + +Use `bonMotDebugString` and `bonMotDebugAttributedString` to print out a version of any attributed string with all of the special characters and image attachments expanded into human-readable XML: + +```swift +NSAttributedString.composed(of: [ + image, + Special.noBreakSpace, + "Monday", + Special.enDash, + "Friday" + ]).bonMotDebugString + +// Result: +// MondayFriday +``` + +You can use [XML Rules](#xml-parsing) to re-parse the resulting string (except for images) back into an attributed string. You can also save the output of `bonMotDebugString` and use it to validate attributed strings in unit tests. + +## Vertical Text Alignment + +UIKit lets you align labels by top, bottom, or baseline. BonMot includes `TextAlignmentConstraint`, a layout constraint subclass that lets you align labels by cap height and x-height. For some fonts, this is essential to convey the designer’s intention: + +Illustration of different methods of aligning text vertically + +`TextAlignmentConstraint` works with any views that expose a `font` property. It uses Key-Value Observing to watch for changes to the `font` property, and adjust its internal measurements accordingly. This is ideal for use with Dynamic Type: if the user changes the font size of the app, `TextAlignmentConstraint` will update. You can also use it to align a label with a plain view, as illustrated by the red dotted line views in the example above. + +**Warning:** `TextAlignmentConstraint` holds strong references to its `firstItem` and `secondItem` properties. Make sure that a view that is constrained by this constraint does not also hold a strong reference to said constraint, because it will cause a retain cycle. + +You can use `TextAlignmentConstraint` programmatically or in Interface Builder. In code, use it like this: + +```swift +TextAlignmentConstraint.with( + item: someLabel, + attribute: .capHeight, + relatedBy: .equal, + toItem: someOtherLabel, + attribute: .capHeight).isActive = true +``` + +In Interface Builder, start by constraining two views to each other with a `top` constraint. Select the constraint, and in the Identity Inspector, change the class to `TextAlignmentConstraint`: + +setting the class in the Identity Inspector + +Next, switch to the Attributes Inspector. `TextAlignmentConstraint` exposes two text fields through [IBInspectables](https://developer.apple.com/library/ios/recipes/xcode_help-IB_objects_media/Chapters/CreatingaLiveViewofaCustomObject.html). Type in the attributes you want to align. You will get a run-time error if you enter an invalid value. + +setting the alignment attributes in the Attributes Inspector + +The layout won’t change in Interface Builder (IBDesignable is not supported for constraint subclasses), but it will work when you run your code. + +**Note:** some of the possible alignment values are not supported in all configurations. Check out [Issue #37](https://github.com/Raizlabs/BonMot/issues/37) for updates. + +# Objective-C Compatibility + +BonMot is written in Swift, but you have a few options if you must use it in an Objective-C code base: + +- For legacy Objective-C code bases, consider using [BonMot 3.2](https://github.com/Raizlabs/BonMot/releases/tag/3.2), the last major release to be written in Objective-C. Make sure you reference the ReadMe from that tagged release, since the syntax is different than BonMot 4.0 and later. +- If you are mixing Objective-C and Swift, you can create named styles as in the [Interface Builder section](#storyboard-and-xib-integration), and then access those styles in Objective-C: + + ```objc +UILabel *label = [[UILabel alloc] init]; +label.bonMotStyleName = @"MyHeadline"; + ``` + +- Use the inspectable properties of common UIKit elements as in the [Interface Builder section](#storyboard-and-xib-integration). + +# BonMot 3 → 4 Migration Guide + +BonMot 4 is a major update, but there are some common patterns that you can use to ease the transition. Note that this is mostly for Swift projects that were using BonMot 3. BonMot 4 has only limited [support for Objective-C](#objective-c-compatibility), so please check that section before attempting to upgrade if you need to maintain Objective-C compatibility. + +### Separating Style from Content + +BonMot 4 introduces the `StringStyle` struct, which encapsulates style information. When you apply a `StringStyle` to a plain `String`, the result is an `NSAttributedString`. This differs from BonMot 3, where a `BONChain` or `BONText` contained both style and string information. The decoupling of content from style follows in the footsteps of HTML/CSS, and makes it easier to test and reason about each component separately from the other. + +### Inline Styling + +The changes required to support inline styling are minimal. It won’t be a completely mechanical process due to some renaming that took place in 4.0, but it should be fairly straightforward: + +##### BonMot 3 + +```swift +let chain = BONChain() + .color(myColor) + .font(myFont) + .figureSpacing(.Tabular) + .alignment(.Center) + .string(text) +label.attributedText = chain.attributedString +``` + +##### BonMot 4 + +```swift +label.attributedText = text.styled( + with: + .color(myColor), + .font(myFont), + .numberSpacing(.monospaced), // renamed in 4.0 + .alignment(.center) +) +``` + +### Saved Styles + +In BonMot 3, you may have stored `BONChain`s for later use. You can accomplish the same thing with BonMot 4’s `StringStyle`, with one main difference: while a `BONChain` can contain a string, a `StringStyle` never does. It is applied to a string, producing an `NSAttributedString`: + +##### BonMot 3 + +```swift +struct Constants { + + static let myChain = BONChain() + .color(myColor) + .font(myFont) + .tagStyles([ + "bold": myBoldChain, + ]) + +} + +// and then, later: + +let attrString = myChain.string("some string").attributedString +``` + +##### BonMot 4 + +```swift +struct Constants { + + static let myStyle = StringStyle( + .color(myColor), + .font(myFont), + .xmlRules([ + .style("bold", myBoldStyle), + ])) + +} + +// and then, later: + +let attrString = "some string".styled(with: Constants.myStyle) +``` + +# Installation + +## CocoaPods + +BonMot is available through [CocoaPods](http://cocoapods.org). To install +it, simply add the following line to your Podfile: + +```ruby +pod 'BonMot' +``` + +## Carthage + +BonMot is also compatible with [Carthage](https://github.com/Carthage/Carthage). To install it, simply add the following line to your Cartfile: + +```ogdl +github "Raizlabs/BonMot" +``` + +# Contributing + +Issues and pull requests are welcome! Please ensure that you have the latest [SwiftLint](https://github.com/realm/SwiftLint) installed before committing and that there are no style warnings generated when building. + +Contributors are expected to abide by the [Contributor Covenant Code of Conduct](https://github.com/Raizlabs/BonMot/blob/master/CONTRIBUTING.md). + +# Author + +Zev Eisenberg: [zev.eisenberg@raizlabs.com](mailto:zev.eisenberg@raizlabs.com), [@ZevEisenberg](https://twitter.com/zeveisenberg) + +Logo by Jon Lopkin: [@jonlopkin](https://twitter.com/jonlopkin) + +# License + +BonMot is available under the MIT license. See the LICENSE file for more info. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/AccessibilityHeadingLevel.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/AccessibilityHeadingLevel.swift new file mode 100644 index 0000000..36a18cb --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/AccessibilityHeadingLevel.swift @@ -0,0 +1,19 @@ +// +// AccessibilityHeadingLevel.swift +// BonMot +// +// Created by Zev Eisenberg on 9/21/17. +// Copyright © 2017 Raizlabs. All rights reserved. +// + +public enum HeadingLevel: Int { + + case none = 0 + case one = 1 + case two = 2 + case three = 3 + case four = 4 + case five = 5 + case six = 6 + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Compatibility.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Compatibility.swift new file mode 100644 index 0000000..4ebec7e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Compatibility.swift @@ -0,0 +1,122 @@ +// +// _Compatibility.swift +// BonMot +// +// Created by Brian King on 8/24/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +/// This file declares extensions to system types to provide a compatible API +/// between Swift iOS, macOS, watchOS, and tvOS. + +#if swift(>=4.2) +#else + extension NSAttributedString { + + public typealias Key = NSAttributedStringKey + + } +#endif + +#if os(OSX) + #if swift(>=4.2) + #else + public typealias NSLineBreakMode = NSParagraphStyle.LineBreakMode + #endif +#else + public extension NSParagraphStyle { + + typealias LineBreakMode = NSLineBreakMode + + } + + #if os(iOS) || os(tvOS) || os(watchOS) + #if swift(>=4.2) + #else + extension UIFontDescriptor { + + public typealias SymbolicTraits = UIFontDescriptorSymbolicTraits + + } + #endif + + extension NSAttributedString.Key { + #if swift(>=4.2) + #else + static let accessibilitySpeechPunctuation = NSAttributedString.Key(UIAccessibilitySpeechAttributePunctuation) + static let accessibilitySpeechLanguage = NSAttributedString.Key(UIAccessibilitySpeechAttributeLanguage) + static let accessibilitySpeechPitch = NSAttributedString.Key(UIAccessibilitySpeechAttributePitch) + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, *) + static let accessibilitySpeechIPANotation = NSAttributedString.Key(UIAccessibilitySpeechAttributeIPANotation) + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, *) + static let accessibilitySpeechQueueAnnouncement = NSAttributedString.Key(UIAccessibilitySpeechAttributeQueueAnnouncement) + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, *) + static let accessibilityTextHeadingLevel = NSAttributedString.Key(UIAccessibilityTextAttributeHeadingLevel) + #endif + } + #endif + + #if os(iOS) || os(tvOS) + #if swift(>=4.2) + #else + public extension NSLayoutConstraint { + + typealias Attribute = NSLayoutAttribute + typealias Relation = NSLayoutRelation + } + + extension UIFont { + + public typealias TextStyle = UIFontTextStyle + + } + + extension UIContentSizeCategory { + + static var didChangeNotification: NSNotification.Name { + return NSNotification.Name.UIContentSizeCategoryDidChange + } + + } + + extension UIViewController { + + var children: [UIViewController] { + return childViewControllers + } + + } + + extension UIApplication { + + public typealias LaunchOptionsKey = UIApplicationLaunchOptionsKey + + } + + extension UITableView { + + public static let automaticDimension = UITableViewAutomaticDimension + + } + + #endif + #endif +#endif + +#if swift(>=4.1) +#else + extension Array { + func compactMap(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult] { + return try flatMap(transform) + } + } +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Composable.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Composable.swift new file mode 100644 index 0000000..e5f7fc6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Composable.swift @@ -0,0 +1,303 @@ +// +// Composable.swift +// BonMot +// +// Created by Brian King on 9/28/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +/// Describes types which know how to append themselves to an attributed string. +/// Used to provide a flexible, extensible chaning API for BonMot. +public protocol Composable { + + /// Append the receiver to a given attributed string. It is up to the + /// receiver's type to define what it means to be appended to an attributed + /// string. Typically, the receiver will pick up the attributes of the last + /// character of the passed attributed string, but the `baseStyle` parameter + /// can be used to provide additional attributes for the appended string. + /// + /// - Parameters: + /// - attributedString: The attributed string to which to append the + /// receiver. + /// - baseStyle: Additional attribues to apply to the receiver before + /// appending it to the passed attributed string. + func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle) + + /// Append the receiver to a given attributed string. It is up to the + /// receiver's type to define what it means to be appended to an attributed + /// string. Typically, the receiver will pick up the attributes of the last + /// character of the passed attributed string, but the `baseStyle` parameter + /// can be used to provide additional attributes for the appended string. + /// + /// - Parameters: + /// - attributedString: The attributed string to which to append the + /// receiver. + /// - baseStyle: Additional attribues to apply to the receiver before + /// appending it to the passed attributed string. + /// - isLastElement: Whether the receiver is the final element that is + /// being appended to an attributed string. Used in cases + /// where the receiver wants to customize how it is + /// appended if it knows it is the last element, chiefly + /// regarding NSAttributedStringKey.kern. + func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle, isLastElement: Bool) + +} + +public extension Composable { + + func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle) { + append(to: attributedString, baseStyle: baseStyle, isLastElement: false) + } + + /// Create an attributed string with only this composable content, and no + /// base style. + /// + /// - returns: a new `NSAttributedString` + public func attributedString() -> NSAttributedString { + return .composed(of: [self]) + } + + /// Create a new `NSAttributedString` with the style specified. + /// + /// - parameter style: The style to use. + /// - parameter overrideParts: The style parts to override on the base style. + /// - parameter stripTrailingKerning: whether to strip NSAttributedStringKey.kern + /// from the last character of the result. + /// - returns: A new `NSAttributedString`. + public func styled(with style: StringStyle, _ overrideParts: StringStyle.Part..., stripTrailingKerning: Bool = true) -> NSAttributedString { + let string = NSMutableAttributedString() + let newStyle = style.byAdding(stringStyle: StringStyle(overrideParts)) + append(to: string, baseStyle: newStyle, isLastElement: stripTrailingKerning) + return string + } + + /// Create a new `NSAttributedString` with the style parts specified. + /// + /// - parameter parts: The style parts to use. + /// - parameter stripTrailingKerning: whether to strip NSAttributedStringKey.kern + /// from the last character of the result. + /// - returns: A new `NSAttributedString`. + public func styled(with parts: StringStyle.Part..., stripTrailingKerning: Bool = true) -> NSAttributedString { + var style = StringStyle() + for part in parts { + style.update(part: part) + } + return styled(with: style, stripTrailingKerning: stripTrailingKerning) + } + +} + +public extension NSAttributedString { + + /// Compose an `NSAttributedString` by concatenating every item in + /// `composables` with `baseStyle` applied. The `separator` is inserted + /// between every item. `baseStyle` acts as the default style, and apply to + /// the `Composable` item only if the `Composable` does not have a style + /// value configured. + /// + /// - parameter composables: An array of `Composable` to join into an + /// `NSAttributedString`. + /// - parameter baseStyle: The base style to apply to every `Composable`. + /// If no `baseStyle` is supplied, no additional + /// styling will be added. + /// - parameter separator: The separator to insert between every pair of + /// elements in `composables`. + /// - returns: A new `NSAttributedString`. + @nonobjc public static func composed(of composables: [Composable], baseStyle: StringStyle = StringStyle(), separator: Composable? = nil) -> NSAttributedString { + let string = NSMutableAttributedString() + string.beginEditing() + let lastComposableIndex = composables.endIndex + for (index, composable) in composables.enumerated() { + composable.append(to: string, baseStyle: baseStyle, isLastElement: index == lastComposableIndex - 1) + if let separator = separator { + if index != composables.indices.last { + separator.append(to: string, baseStyle: baseStyle) + } + } + } + string.endEditing() + return string + } + + public func styled(with style: StringStyle, _ overrideParts: StringStyle.Part...) -> NSAttributedString { + let newStyle = style.byAdding(overrideParts) + let newAttributes = newStyle.attributes + + let mutableSelf = mutableStringCopy() + let fullRange = NSRange(location: 0, length: mutableSelf.string.utf16.count) + + for (key, value) in newAttributes { + mutableSelf.addAttribute(key, value: value, range: fullRange) + } + return mutableSelf.immutableCopy() + } + +} + +extension NSAttributedString: Composable { + + /// Append this `NSAttributedString` to `attributedString`, with `baseStyle` + /// applied as default values. This method enumerates all attribute ranges + /// in the receiver and use `baseStyle` to supply defaults for the attributes. + /// This effectively merges `baseStyle` and the embedded attributes, with a + /// tie going to the embedded attributes. + /// + /// See `StringStyle.supplyDefaults(for:)` for more details. + /// + /// - parameter to: The attributed string to which to append the receiver. + /// - parameter baseStyle: The `StringStyle` that is overridden by the + /// receiver's attributes + @nonobjc public final func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle, isLastElement: Bool) { + let range = NSRange(location: 0, length: length) + enumerateAttributes(in: range, options: []) { (attributes, range, _) in + let substring = self.attributedSubstring(from: range) + // Add the string with the defaults supplied by the style + let newString = baseStyle.attributedString(from: substring.string, existingAttributes: attributes) + attributedString.append(newString) + } + + if isLastElement { + attributedString.removeKerningFromLastCharacter() + } + else { + attributedString.restoreKerningOnLastCharacter() + } + } + +} + +extension String: Composable { + + /// Append the receiver to `attributedString`, with `baseStyle` applied as + /// default values. Since `String` has no style, `baseStyle` is the only + /// style that is used. + /// + /// - parameter to: The attributed string to which to append the receiver. + /// - parameter baseStyle: The style to use for this string. + public func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle, isLastElement: Bool) { + attributedString.append(baseStyle.attributedString(from: self)) + if isLastElement { + attributedString.removeKerningFromLastCharacter() + } + else { + attributedString.restoreKerningOnLastCharacter() + } + } + +} + +#if os(iOS) || os(tvOS) || os(OSX) +extension BONImage: Composable { + + /// Append the receiver to `attributedString`, with `baseStyle` applied as + /// default values. Only a few properties in `baseStyle` are relevant when + /// styling images. These include `baselineOffset`, as well as `color` for + /// template images. All attributes are stored in the range of the image for + /// consistency inside the attributed string. + /// + /// - note: the `NSBaselineOffsetAttributeName` value is used as the + /// `bounds.origin.y` value for the text attachment, and is removed from the + /// attributes dictionary to fix an issue with UIKit. + /// + /// - note: `NSTextAttachment` is not available on watchOS. + /// + /// - parameter to: The attributed string to which to append the receiver. + /// - parameter baseStyle: The style to use. + @nonobjc public final func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle, isLastElement: Bool) { + let baselinesOffsetForAttachment = baseStyle.baselineOffset ?? 0 + let attachment = NSTextAttachment() + + #if os(OSX) + let imageIsTemplate = isTemplate + #else + let imageIsTemplate = (renderingMode != .alwaysOriginal) + #endif + + var imageToUse = self + if let color = baseStyle.color { + if imageIsTemplate { + imageToUse = tintedImage(color: color) + } + } + attachment.image = imageToUse + + attachment.bounds = CGRect(origin: CGPoint(x: 0, y: baselinesOffsetForAttachment), size: size) + + let attachmentString = NSAttributedString(attachment: attachment).mutableStringCopy() + // Remove the baseline offset from the attributes so it isn't applied twice + var attributes = baseStyle.attributes + attributes[.baselineOffset] = nil + attachmentString.addAttributes(attributes, range: NSRange(location: 0, length: attachmentString.length)) + + attributedString.append(attachmentString) + } + +} +#endif + +extension Special: Composable { + + /// Append the receiver's string value to `attributedString`, with `baseStyle` + /// applied as default values. + /// + /// - parameter to: The attributed string to which to append the receiver. + /// - parameter baseStyle: The style to use. + public func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle, isLastElement: Bool) { + description.append(to: attributedString, baseStyle: baseStyle) + } + +} + +public extension Sequence where Element: Composable { + + func joined(separator: Composable = "") -> NSAttributedString { + return NSAttributedString.composed(of: Array(self), separator: separator) + } + +} + +extension NSAttributedString.Key { + + public static let bonMotRemovedKernAttribute = NSAttributedString.Key("com.raizlabs.bonmot.removedKernAttributeRemoved") + +} + +extension NSMutableAttributedString { + + func removeKerningFromLastCharacter() { + guard length != 0 else { + return + } + + let lastCharacterRange = NSRange(location: length - 1, length: 1) + + guard let currentKernValue = attribute(.kern, at: lastCharacterRange.location, effectiveRange: nil) else { + return + } + + removeAttribute(.kern, range: lastCharacterRange) + addAttribute(.bonMotRemovedKernAttribute, value: currentKernValue, range: lastCharacterRange) + } + + func restoreKerningOnLastCharacter() { + guard length != 0 else { + return + } + + let lastCharacterRange = NSRange(location: length - 1, length: 1) + + guard let currentKernValue = attribute(.bonMotRemovedKernAttribute, at: lastCharacterRange.location, effectiveRange: nil) else { + return + } + + removeAttribute(.bonMotRemovedKernAttribute, range: lastCharacterRange) + addAttribute(.kern, value: currentKernValue, range: lastCharacterRange) + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/ContextualAlternates.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/ContextualAlternates.swift new file mode 100644 index 0000000..f92a3ea --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/ContextualAlternates.swift @@ -0,0 +1,92 @@ +// +// ContextualAlternates.swift +// BonMot +// +// Created by Zev Eisenberg on 11/5/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +// This is not supported on watchOS +#if os(iOS) || os(tvOS) || os(OSX) + + /// Different contextual alternates available for customizing a font. Not + /// all fonts support all (or any) of these options. + public struct ContextualAlternates { + + var contextualAlternates: Bool? + var swashAlternates: Bool? + var contextualSwashAlternates: Bool? + + public init() { } + + } + + // Convenience constructors + extension ContextualAlternates { + + public static func contextualAlternates(on isOn: Bool) -> ContextualAlternates { + var alts = ContextualAlternates() + alts.contextualAlternates = isOn + return alts + } + + public static func swashAlternates(on isOn: Bool) -> ContextualAlternates { + var alts = ContextualAlternates() + alts.swashAlternates = isOn + return alts + } + + public static func contextualSwashAlternates(on isOn: Bool) -> ContextualAlternates { + var alts = ContextualAlternates() + alts.contextualSwashAlternates = isOn + return alts + } + + } + + extension ContextualAlternates { + + mutating public func add(other theOther: ContextualAlternates) { + contextualAlternates = theOther.contextualAlternates ?? contextualAlternates + swashAlternates = theOther.swashAlternates ?? swashAlternates + contextualSwashAlternates = theOther.contextualSwashAlternates ?? contextualSwashAlternates + } + + public func byAdding(other theOther: ContextualAlternates) -> ContextualAlternates { + var varSelf = self + varSelf.add(other: theOther) + return varSelf + } + + } + + extension ContextualAlternates: FontFeatureProvider { + + public func featureSettings() -> [(type: Int, selector: Int)] { + var selectors = [Int]() + + if let contextualAlternates = contextualAlternates { + selectors.append(contextualAlternates ? kContextualAlternatesOnSelector : kContextualAlternatesOffSelector) + } + if let swashAlternates = swashAlternates { + selectors.append(swashAlternates ? kSwashAlternatesOnSelector : kSwashAlternatesOffSelector) + } + if let contextualSwashAlternates = contextualSwashAlternates { + selectors.append(contextualSwashAlternates ? kContextualSwashAlternatesOnSelector : kContextualSwashAlternatesOffSelector) + } + + return selectors.map { (type: kContextualAlternatesType, selector: $0) } + } + + } + + public func + (lhs: ContextualAlternates, rhs: ContextualAlternates) -> ContextualAlternates { + return lhs.byAdding(other: rhs) + } +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Emphasis.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Emphasis.swift new file mode 100644 index 0000000..d43c044 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Emphasis.swift @@ -0,0 +1,68 @@ +// +// Emphasis.swift +// BonMot +// +// Created by Zev Eisenberg on 2/12/18. +// Copyright © 2018 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +public struct Emphasis: OptionSet { + + public var rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + public static let italic = Emphasis(rawValue: 1 << 0) + public static let bold = Emphasis(rawValue: 1 << 1) + + // Reserved for later use, if we figure out a good naming scheme and use case. + private static let expanded = Emphasis(rawValue: 1 << 2) + private static let condensed = Emphasis(rawValue: 1 << 3) + private static let vertical = Emphasis(rawValue: 1 << 4) + private static let uiOptimized = Emphasis(rawValue: 1 << 5) + private static let tightLineSpacing = Emphasis(rawValue: 1 << 6) // AKA Tight Leading + private static let looseLineSpacing = Emphasis(rawValue: 1 << 7) // AKA Loose Leading + +} + +extension Emphasis { + + var symbolicTraits: BONSymbolicTraits { + var traits: BONSymbolicTraits = [] + if contains(.italic) { + traits.insert(.italic) + } + if contains(.bold) { + traits.insert(.bold) + } + if contains(.expanded) { + traits.insert(.expanded) + } + if contains(.condensed) { + traits.insert(.condensed) + } + if contains(.vertical) { + traits.insert(.vertical) + } + if contains(.uiOptimized) { + traits.insert(.uiOptimized) + } + if contains(.tightLineSpacing) { + traits.insert(.tightLineSpacing) + } + if contains(.looseLineSpacing) { + traits.insert(.looseLineSpacing) + } + + return traits + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/FontFeatures.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/FontFeatures.swift new file mode 100644 index 0000000..0f03b51 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/FontFeatures.swift @@ -0,0 +1,220 @@ +// +// FontFeatures.swift +// BonMot +// +// Created by Brian King on 8/31/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +// This is not supported on watchOS +#if os(iOS) || os(tvOS) || os(OSX) + + /// Protocol to provide values to be used by `UIFontFeatureTypeIdentifierKey` + /// and `UIFontFeatureSelectorIdentifierKey`. You can typically find these + /// values in CoreText.SFNTLayoutTypes. + public protocol FontFeatureProvider { + func featureSettings() -> [(type: Int, selector: Int)] + } + + public extension BONFont { + + /// Create a new font and attempt to enable the specified font features. + /// The returned font will have all features enabled that it supports. + /// - parameter withFeatures: the features to attempt to enable on the + /// font. + /// - returns: a new font with the specified features enabled. + public func font(withFeatures featureProviders: [FontFeatureProvider]) -> BONFont { + + guard featureProviders.count > 0 else { + return self + } + + let newFeatures = featureProviders.flatMap { $0.featureAttributes() } + + guard newFeatures.count > 0 else { + return self + } + + var fontAttributes = fontDescriptor.fontAttributes + var features = fontAttributes[BONFontDescriptorFeatureSettingsAttribute] as? [[BONFontDescriptor.FeatureKey: Any]] ?? [] + + features.append(contentsOf: newFeatures) + fontAttributes[BONFontDescriptorFeatureSettingsAttribute] = features + + let descriptor = BONFontDescriptor(fontAttributes: fontAttributes) + #if os(OSX) + return BONFont(descriptor: descriptor, size: pointSize)! + #else + return BONFont(descriptor: descriptor, size: pointSize) + #endif + } + + } + + /// A feature provider for changing the number case, also known as "figure + /// style". + public enum NumberCase: FontFeatureProvider { + + /// Uppercase numbers, also known as "lining figures", are the same height + /// as uppercase letters, and they do not extend below the baseline. + case upper + + /// Lowercase numbers, also known as "oldstyle figures", are similar in + /// size and visual weight to lowercase letters, allowing them to + /// blend in better in a block of text. They may have descenders + /// which drop below the typographic baseline. + case lower + + public func featureSettings() -> [(type: Int, selector: Int)] { + switch self { + case .upper: + return [(type: kNumberCaseType, selector: kUpperCaseNumbersSelector)] + case .lower: + return [(type: kNumberCaseType, selector: kLowerCaseNumbersSelector)] + } + } + + } + + /// A feature provider for changing the number spacing, also known as + /// "figure spacing". + public enum NumberSpacing: FontFeatureProvider { + + /// Monospaced numbers, also known as "tabular figures", each take up + /// the same amount of horizontal space, meaning that different numbers + /// will line up when arranged in columns. + case monospaced + + /// Proportionally spaced numbers, also known as "proprotional figures", + /// are of variable width. This makes them look better in most cases, + /// but they should be avoided when numbers need to line up in columns. + case proportional + + public func featureSettings() -> [(type: Int, selector: Int)] { + switch self { + case .monospaced: + return [(type: kNumberSpacingType, selector: kMonospacedNumbersSelector)] + case .proportional: + return [(type: kNumberSpacingType, selector: kProportionalNumbersSelector)] + } + } + + } + + /// A feature provider for displaying a fraction. + public enum Fractions: FontFeatureProvider { + + /// No fraction formatting. + case disabled + + /// Diagonal Fractions, when written on paper, are written on one line + /// with the numerator diagonally above and to the left of the + /// demoninator, with the slash ("/") between them. + case diagonal + + /// Vertical Fractions, when written on paper, are written on one line + /// with the numerator directly above the + /// demoninator, with a line lying horizontally between them. + case vertical + + public func featureSettings() -> [(type: Int, selector: Int)] { + switch self { + case .disabled: + return [(type: kFractionsType, selector: kNoFractionsSelector)] + case .diagonal: + return [(type: kFractionsType, selector: kDiagonalFractionsSelector)] + case .vertical: + return [(type: kFractionsType, selector: kVerticalFractionsSelector)] + } + } + + } + + /// A feature provider for changing the vertical position of characters + /// using predefined styles in the font, such as superscript and subscript. + public enum VerticalPosition: FontFeatureProvider { + + /// No vertical position adjustment is applied. + case normal + + /// Superscript (superior) glpyh variants are used, as in footnotes¹. + case superscript + + /// Subscript (inferior) glyph variants are used: vₑ. + case `subscript` + + /// Ordinal glyph variants are used, as in the common typesetting of 4th. + case ordinals + + /// Scientific inferior glyph variants are used: H₂O + case scientificInferiors + + public func featureSettings() -> [(type: Int, selector: Int)] { + let selector: Int + switch self { + case .normal: selector = kNormalPositionSelector + case .superscript: selector = kSuperiorsSelector + case .`subscript`: selector = kInferiorsSelector + case .ordinals: selector = kOrdinalsSelector + case .scientificInferiors: selector = kScientificInferiorsSelector + } + return [(type: kVerticalPositionType, selector: selector)] + } + + } + + /// A feature provider for changing small caps behavior. + /// - Note: `fromUppercase` and `fromLowercase` can be combined: they are not + /// mutually exclusive. + public enum SmallCaps: FontFeatureProvider { + + /// No small caps are used. + case disabled + + /// Uppercase letters in the source string are replaced with small caps. + /// Lowercase letters remain unmodified. + case fromUppercase + + /// Lowercase letters in the source string are replaced with small caps. + /// Uppercase letters remain unmodified. + case fromLowercase + + public func featureSettings() -> [(type: Int, selector: Int)] { + switch self { + case .disabled: + return [ + (type: kLowerCaseType, selector: kDefaultLowerCaseSelector), + (type: kUpperCaseType, selector: kDefaultUpperCaseSelector), + ] + case .fromUppercase: + return [(type: kUpperCaseType, selector: kUpperCaseSmallCapsSelector)] + case .fromLowercase: + return [(type: kLowerCaseType, selector: kLowerCaseSmallCapsSelector)] + } + } + + } + + extension FontFeatureProvider { + + /// - returns: an array of dictionaries, each representing one feature + /// for the attributes key in the font attributes dictionary. + func featureAttributes() -> [[BONFontDescriptor.FeatureKey: Any]] { + let featureSettings = self.featureSettings() + return featureSettings.map { + return [ + BONFontFeatureTypeIdentifierKey: $0.type, + BONFontFeatureSelectorIdentifierKey: $0.selector, + ] + } + } + + } + +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/FontInspector.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/FontInspector.swift new file mode 100644 index 0000000..73f7730 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/FontInspector.swift @@ -0,0 +1,216 @@ +// +// FontInspector.swift +// BonMot +// +// Created by Zev Eisenberg on 11/2/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +// This is not supported on watchOS +#if os(iOS) || os(tvOS) || os(OSX) + import Foundation + import CoreText + + typealias FontFeatureDictionary = [String: Any] + + public extension BONFont { + + public func has(feature theFeature: MappableFeature) -> Bool { + let matchingFeatures = availableFeaturesDictionaries.filter { featureDict in + guard let featureTypeIdentifier = featureDict[kCTFontFeatureTypeIdentifierKey as String] as? Int else { + return false + } + + return theFeature.featureTypeIdentifiers.contains(featureTypeIdentifier) + } + + return !matchingFeatures.isEmpty + } + + /// Queries a font and returns its available OpenType features. + /// + /// - Parameter includeIDs: whether to include the integer values of the + /// features' type identifiers, which are + /// integers, and pretty cryptic unless you know + /// what you're looking for. + /// - Returns: A human-readable string representing the receiver's + /// available OpenType features. + /// - Note: features will report whether they are "Exclusive". If a + /// feature is exclusive, that means that you can use only one + /// of its available options at a time. Otherwise, you can mix + /// and match any combination of its options. + public func availableFontFeatures(includeIdentifiers includeIDs: Bool = false) -> String { + let preamble = "Available font features of \(fontName)" + let features: [String] = availableFeaturesDictionaries.map { featureDict in + let featureName = featureDict[kCTFontFeatureTypeNameKey as String] as? String + let exclusive = featureDict[kCTFontFeatureTypeExclusiveKey as String] as? Bool ?? false + let selectors = featureDict[kCTFontFeatureTypeSelectorsKey as String] as? [FontFeatureDictionary] ?? [] + + var resultString = "" + resultString += "\(featureName ?? "[unknown feature]")" + if includeIDs { + let featureTypeIdentifier = featureDict[kCTFontFeatureTypeIdentifierKey as String] as? Int + resultString += " - feature type identifier: \(featureTypeIdentifier.map(String.init(describing:)) ?? "[unknown feature identifier]")" + } + resultString += "\n Exclusive: \(exclusive)" + if !selectors.isEmpty { + resultString += "\n Selectors:" + let selectorStrings: [String] = selectors.map { selectorDict in + let selectorName = selectorDict[kCTFontFeatureSelectorNameKey as String] as? String + let selectorIsDefault = selectorDict[kCTFontFeatureSelectorDefaultKey as String] as? Bool ?? false + + var resultString = "" + resultString += " * \(selectorName ?? "[unknown selector]")" + if includeIDs { + let selectorIdentifier = selectorDict[kCTFontFeatureSelectorIdentifierKey as String] as? Int + resultString += " - selector: \(selectorIdentifier.map(String.init(describing:)) ?? "[unknownSelectorIdentifier]")" + } + if selectorIsDefault { + resultString += " (default)" + } + return resultString + } + resultString += selectorStrings.reduce("") { $0 + "\n" + $1 } + } + return resultString + } + return preamble + features.reduce("") { $0 + "\n\n" + $1 } + } + + } + + private extension BONFont { + + /// Wrapper around `CTFontCopyFeatures()`, mostly to deal with Swift type shenanigans. + var availableFeaturesDictionaries: [FontFeatureDictionary] { + let coreTextFont = CTFontCreateWithName( + fontName as CFString, + pointSize, + nil) + + guard let features = CTFontCopyFeatures(coreTextFont) else { + return [] + } + + guard let typedFeatures = features as? [FontFeatureDictionary] else { + fatalError("failed to convert to \([FontFeatureDictionary].self) from \(features)") + } + + return typedFeatures + + } + + } + + /// Home-grown mapping of font features. To add more entries, call + /// `availableFontFeatures(includeIdentifiers: true)` on a font and see what + /// it spits out. The best documentation on the subject I could find is on + /// [this Apple discussion thread]( http://lists.apple.com/archives/coretext-dev/2011/Jan/msg00004.html ). + /// + /// **From user Wim Lewis on that thread:** + /// > It's not clear to me if there's any way to translate between the + /// > CTFeatureTypeIdentifier values and the standard 4-character tags for + /// > font features. (I would have assumed that the CTFeatureTypeIdentifier + /// > values *were* the FourCCs of the feature types, but looking at them + /// > just now they appear to be small integers.) + /// + /// **And a reply from Ned Holbrook:** + /// > Currently all feature settings are expressed in terms of the AAT + /// > features rather than OT features. Predefined AAT features can be found + /// > in the header on the desktop, but fonts can + /// > define their own features as well. + public enum FeatureTypeIdentifier: Int { + + case allTypographicFeatures = 0 + case ligatures = 1 + case numberSpacing = 6 + case verticalPosition = 10 + case contextualFractionalForms = 11 + case ornaments = 16 + case stylisticVariants = 18 + case numberCase = 21 + case textSpacing = 22 + case caseSensitiveLayout = 33 + case stylisticAlternates = 35 + case contextualAlternates = 36 + case lowerCase = 37 + case upperCase = 38 + case special = 128 + + } + + /// Describes a type which can vend up an array of font feature type + /// identifiers. + public protocol MappableFeature { + + /// The feature type identifier or identifiers which comprise this + /// font feature. Most of these values are not explicitly documented, + /// but many can be found in the BonMot.FeatureTypeIdentifier enum. + var featureTypeIdentifiers: [Int] { get } + + } + + extension NumberCase: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + return [FeatureTypeIdentifier.numberCase.rawValue] + } + + } + + extension NumberSpacing: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + return [FeatureTypeIdentifier.numberSpacing.rawValue] + } + + } + + extension Fractions: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + return [FeatureTypeIdentifier.contextualFractionalForms.rawValue] + } + + } + + extension VerticalPosition: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + return [FeatureTypeIdentifier.verticalPosition.rawValue] + } + + } + + extension SmallCaps: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + switch self { + case .disabled: + return [ + FeatureTypeIdentifier.upperCase.rawValue, + FeatureTypeIdentifier.lowerCase.rawValue, + ] + case .fromUppercase: return [ FeatureTypeIdentifier.upperCase.rawValue ] + case .fromLowercase: return [ FeatureTypeIdentifier.lowerCase.rawValue ] + } + } + + } + + extension StylisticAlternates: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + return [ FeatureTypeIdentifier.stylisticAlternates.rawValue ] + } + + } + + extension ContextualAlternates: MappableFeature { + + public var featureTypeIdentifiers: [Int] { + return [ FeatureTypeIdentifier.contextualAlternates.rawValue ] + } + + } +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Image+Tinting.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Image+Tinting.swift new file mode 100644 index 0000000..9c97d3b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Image+Tinting.swift @@ -0,0 +1,128 @@ +// +// Image+Tinting.swift +// BonMot +// +// Created by Zev Eisenberg on 9/28/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import Foundation + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +public extension BONImage { + + #if os(OSX) + /// Returns a copy of the receiver where the alpha channel is maintained, + /// but every pixel's color is replaced with `color`. + /// + /// - note: The returned image does _not_ have the template flag set, + /// preventing further tinting. + /// + /// - Parameter theColor: The color to use to tint the receiver. + /// - Returns: A tinted copy of the image. + @objc(bon_tintedImageWithColor:) + func tintedImage(color theColor: BONColor) -> BONImage { + let imageRect = CGRect(origin: .zero, size: size) + + let image = NSImage(size: size) + + let rep = NSBitmapImageRep( + bitmapDataPlanes: nil, + pixelsWide: Int(size.width), + pixelsHigh: Int(size.height), + bitsPerSample: 8, + samplesPerPixel: 4, + hasAlpha: true, + isPlanar: false, + colorSpaceName: theColor.colorSpaceName, + bytesPerRow: 0, + bitsPerPixel: 0 + )! + + image.addRepresentation(rep) + + image.lockFocus() + + let context = NSGraphicsContext.current!.cgContext + + context.setBlendMode(.normal) + let cgImage = self.cgImage(forProposedRect: nil, context: nil, hints: nil)! + context.draw(cgImage, in: imageRect) + + // .sourceIn: resulting color = source color * destination alpha + context.setBlendMode(.sourceIn) + context.setFillColor(theColor.cgColor) + context.fill(imageRect) + + image.unlockFocus() + + // Prevent further tinting + image.isTemplate = false + + // Transfer accessibility description + image.accessibilityDescription = self.accessibilityDescription + + return image + } + #else + /// Returns a copy of the receiver where the alpha channel is maintained, + /// but every pixel's color is replaced with `color`. + /// + /// - note: The returned image does _not_ have the template flag set, + /// preventing further tinting. + /// + /// - Parameter theColor: The color to use to tint the receiver. + /// - Returns: A tinted copy of the image. + @objc(bon_tintedImageWithColor:) + func tintedImage(color theColor: BONColor) -> BONImage { + let imageRect = CGRect(origin: .zero, size: size) + // Save original properties + let originalCapInsets = capInsets + let originalResizingMode = resizingMode + let originalAlignmentRectInsets = alignmentRectInsets + + UIGraphicsBeginImageContextWithOptions(size, false, scale) + let context = UIGraphicsGetCurrentContext()! + + // Flip the context vertically + context.translateBy(x: 0.0, y: size.height) + context.scaleBy(x: 1.0, y: -1.0) + + // Image tinting mostly inspired by http://stackoverflow.com/a/22528426/255489 + + context.setBlendMode(.normal) + context.draw(cgImage!, in: imageRect) + + // .sourceIn: resulting color = source color * destination alpha + context.setBlendMode(.sourceIn) + context.setFillColor(theColor.cgColor) + context.fill(imageRect) + + // Get new image + var image = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + + // Prevent further tinting + image = image.withRenderingMode(.alwaysOriginal) + + // Restore original properties + image = image.withAlignmentRectInsets(originalAlignmentRectInsets) + if originalCapInsets != image.capInsets || originalResizingMode != image.resizingMode { + image = image.resizableImage(withCapInsets: originalCapInsets, resizingMode: originalResizingMode) + } + + // Transfer accessibility label (watchOS not included; does not have accessibilityLabel on UIImage). + #if os(iOS) || os(tvOS) + image.accessibilityLabel = self.accessibilityLabel + #endif + + return image + } + #endif + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Ligatures.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Ligatures.swift new file mode 100644 index 0000000..e14e0a6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Ligatures.swift @@ -0,0 +1,23 @@ +// +// Ligatures.swift +// BonMot +// +// Created by Zev Eisenberg on 11/1/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +/// Different ligature styles for use in attributed strings. +public enum Ligatures: Int { + + /// No ligatures. + case disabled = 0 + + /// Default ligatures. + case defaults = 1 + + #if os(OSX) + /// All ligatures. + case all = 2 + #endif + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/MutableCopying.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/MutableCopying.swift new file mode 100644 index 0000000..2277774 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/MutableCopying.swift @@ -0,0 +1,43 @@ +// +// MutableCopying.swift +// BonMot +// +// Created by Zev Eisenberg on 9/28/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import Foundation + +#if os(iOS) || os(watchOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + +extension NSAttributedString { + + @nonobjc func mutableStringCopy() -> NSMutableAttributedString { + guard let copy = mutableCopy() as? NSMutableAttributedString else { + fatalError("Failed to mutableCopy() \(self)") + } + return copy + } + + @nonobjc func immutableCopy() -> NSAttributedString { + guard let copy = copy() as? NSAttributedString else { + fatalError("Failed to copy() \(self)") + } + return copy + } +} + +extension NSParagraphStyle { + + @nonobjc func mutableParagraphStyleCopy() -> NSMutableParagraphStyle { + guard let copy = mutableCopy() as? NSMutableParagraphStyle else { + fatalError("Failed to mutableCopy() \(self)") + } + return copy + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/NSAttributedString+BonMot.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/NSAttributedString+BonMot.swift new file mode 100644 index 0000000..a1aaf08 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/NSAttributedString+BonMot.swift @@ -0,0 +1,93 @@ +// +// NSAttributedString+BonMot.swift +// BonMot +// +// Created by Brian King on 7/19/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +extension NSAttributedString { + + /// Create a copy of `self`, but replace characters in the `Special` + /// enumeration, images, and unassigned unicode characters with a + /// human-readable string. + public var bonMotDebugAttributedString: NSAttributedString { + let debug = mutableStringCopy() + var replacements = [(range: NSRange, string: String)]() + var index = 0 + + // When looping over `string.unicodeScalars` directly, we saw + // nondeterministic behavior where indices after the first one would + // contain different characters than what was expected. Pulling + /// `unicodeScalars` out first, and then looping, seems to fix it. + let scalars = string.unicodeScalars + + for unicode in scalars { + let replacementString: String? + switch Special(rawValue: unicode) { + case .space?: + replacementString = nil + case .objectReplacementCharacter?: + #if os(iOS) || os(tvOS) || os(OSX) + if let attachment = attribute(.attachment, at: index, effectiveRange: nil) as? NSTextAttachment, let image = attachment.image { + replacementString = String(format: "image size='%.3gx%.3g'", image.size.width, image.size.height) + } + else { + replacementString = Special.objectReplacementCharacter.name + } + #else + replacementString = nil + #endif + case let value: + replacementString = value?.name + } + let utf16Length = String(unicode).utf16.count + if let replacementString = replacementString { + replacements.append((NSRange(location: index, length: utf16Length), replacementString)) + } + index += utf16Length + } + for replacement in replacements.reversed() { + debug.replaceCharacters(in: replacement.range, with: "") + } + replacements = [] + + let unassignedPrefix = "\\N{ Void = { name in + print("Requesting unregistered style \(name)") + } + + /// Create a new `NamedStyles` object with the specified name-to-style + /// mapping. + /// - parameter styles: A dictionary containing the name-to-style mapping + public init(styles: [String: StringStyle] = [:]) { + self.styles = styles + } + + /// The name-to-style mapping + public var styles: [String: StringStyle] + + /// Register a new named style for later retrieval. + /// + /// - Parameters: + /// - name: The name of the new style. If a style is already registered + /// for this name, it is replaced. + /// - style: The style to register. + public func registerStyle(forName name: String, style: StringStyle) { + styles[name] = style + } + + /// Look up a style for the specified name. If no style is found, + /// `NamedStyles.unregisteredStyleClosure` is called. This is done for error + /// reporting and safety. We don't want to crash if no style is found, and + /// we want to avoid adding `throws` everywhere. In general, if a style is + /// requested by name, it will just log, and your text will be un-styled. + /// + /// - parameter forName: The name of the style to look up + /// - returns: the requested style, or `nil` if none is found + public func style(forName name: String) -> StringStyle? { + guard let style = styles[name] else { + NamedStyles.unregisteredStyleClosure(name) + return nil + } + return style + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Platform.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Platform.swift new file mode 100644 index 0000000..2471758 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Platform.swift @@ -0,0 +1,85 @@ +// +// Platform.swift +// BonMot +// +// Created by Brian King on 9/22/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit + public typealias BONColor = NSColor + public typealias BONImage = NSImage + public typealias BONTextField = NSTextField + + public typealias BONFont = NSFont + public typealias BONFontDescriptor = NSFontDescriptor + public typealias BONSymbolicTraits = NSFontDescriptor.SymbolicTraits + let BONFontDescriptorFeatureSettingsAttribute = NSFontDescriptor.AttributeName.featureSettings + let BONFontFeatureTypeIdentifierKey = NSFontDescriptor.FeatureKey.typeIdentifier + let BONFontFeatureSelectorIdentifierKey = NSFontDescriptor.FeatureKey.selectorIdentifier +#else + import UIKit + public typealias BONColor = UIColor + public typealias BONImage = UIImage + + public typealias BONFont = UIFont + public typealias BONFontDescriptor = UIFontDescriptor + public typealias BONSymbolicTraits = UIFontDescriptor.SymbolicTraits + let BONFontDescriptorFeatureSettingsAttribute = UIFontDescriptor.AttributeName.featureSettings + let BONFontFeatureTypeIdentifierKey = UIFontDescriptor.FeatureKey.featureIdentifier + let BONFontFeatureSelectorIdentifierKey = UIFontDescriptor.FeatureKey.typeIdentifier + + #if os(iOS) || os(tvOS) + public typealias BONTextField = UITextField + #endif +#endif + +public typealias StyleAttributes = [NSAttributedString.Key: Any] + +#if os(iOS) || os(tvOS) + public typealias BonMotTextStyle = UIFont.TextStyle + public typealias BonMotContentSizeCategory = UIContentSizeCategory +#endif + +// This key is defined here because it needs to be used in non-adaptive code. +public let BonMotTransformationsAttributeName = NSAttributedString.Key("BonMotTransformations") + +extension BONSymbolicTraits { + #if os(iOS) || os(tvOS) || os(watchOS) + static var italic: BONSymbolicTraits { + return .traitItalic + } + static var bold: BONSymbolicTraits { + return .traitBold + } + static var expanded: BONSymbolicTraits { + return .traitExpanded + } + static var condensed: BONSymbolicTraits { + return .traitCondensed + } + static var vertical: BONSymbolicTraits { + return .traitVertical + } + static var uiOptimized: BONSymbolicTraits { + return .traitUIOptimized + } + static var tightLineSpacing: BONSymbolicTraits { + return .traitTightLeading + } + static var looseLineSpacing: BONSymbolicTraits { + return .traitLooseLeading + } + #else + static var uiOptimized: BONSymbolicTraits { + return .UIOptimized + } + static var tightLineSpacing: BONSymbolicTraits { + return .tightLeading + } + static var looseLineSpacing: BONSymbolicTraits { + return .looseLeading + } + #endif +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Special.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Special.swift new file mode 100644 index 0000000..524654b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Special.swift @@ -0,0 +1,118 @@ +// +// Special.swift +// BonMot +// +// Created by Brian King on 9/1/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +/// Interesting Unicode characters for use in creating strings. Most characters +/// in `Special` are either non-printing (like the various space characters) or +/// visually ambiguous when viewed with a monospace code font (like the dashes +/// and hyphens). +public enum Special: UnicodeScalar { + + // Keep the cases sorted by unichar value when adding new cases. + case tab = "\u{0009}" + case lineFeed = "\u{000A}" + case verticalTab = "\u{000B}" + case formFeed = "\u{000C}" + case carriageReturn = "\u{000D}" + case space = "\u{0020}" + case nextLine = "\u{0085}" + case noBreakSpace = "\u{00A0}" + case enSpace = "\u{2002}" + case emSpace = "\u{2003}" + case figureSpace = "\u{2007}" + case thinSpace = "\u{2009}" + case hairSpace = "\u{200A}" + case zeroWidthSpace = "\u{200B}" + case nonBreakingHyphen = "\u{2011}" + case figureDash = "\u{2012}" + case enDash = "\u{2013}" + case emDash = "\u{2014}" + case horizontalEllipsis = "\u{2026}" + case lineSeparator = "\u{2028}" + case paragraphSeparator = "\u{2029}" + case leftToRightOverride = "\u{202D}" + case narrowNoBreakSpace = "\u{202F}" + case wordJoiner = "\u{2060}" + case minusSign = "\u{2212}" + case objectReplacementCharacter = "\u{FFFC}" // NSAttachmentCharacter + +} + +extension Special: CustomStringConvertible { + + /// A `String` initialized the `UnicodeScalar` of the receiver as its `rawValue`. + public var description: String { + return String(rawValue) + } + +} + +extension Special { + + /// A developer-facing string for this UnicodeValue. Useful for debugging. + public var name: String { + switch self { + case .tab: return "tab" + case .lineFeed: return "lineFeed" + case .verticalTab: return "verticalTab" + case .formFeed: return "formFeed" + case .carriageReturn: return "carriageReturn" + case .space: return "space" + case .nextLine: return "nextLine" + case .noBreakSpace: return "noBreakSpace" + case .enSpace: return "enSpace" + case .emSpace: return "emSpace" + case .figureSpace: return "figureSpace" + case .thinSpace: return "thinSpace" + case .hairSpace: return "hairSpace" + case .zeroWidthSpace: return "zeroWidthSpace" + case .nonBreakingHyphen: return "nonBreakingHyphen" + case .figureDash: return "figureDash" + case .enDash: return "enDash" + case .emDash: return "emDash" + case .horizontalEllipsis: return "horizontalEllipsis" + case .lineSeparator: return "lineSeparator" + case .paragraphSeparator: return "paragraphSeparator" + case .leftToRightOverride: return "leftToRightOverride" + case .narrowNoBreakSpace: return "narrowNoBreakSpace" + case .wordJoiner: return "wordJoiner" + case .minusSign: return "minusSign" + case .objectReplacementCharacter: return "objectReplacementCharacter" + } + } + + /// All of the enum values contained in `Special`. + public static var all: [Special] = [ + .tab, + .lineFeed, + .verticalTab, + .formFeed, + .carriageReturn, + .space, + .nextLine, + .noBreakSpace, + .enSpace, + .emSpace, + .figureSpace, + .thinSpace, + .hairSpace, + .zeroWidthSpace, + .nonBreakingHyphen, + .figureDash, + .enDash, + .emDash, + .horizontalEllipsis, + .lineSeparator, + .paragraphSeparator, + .leftToRightOverride, + .narrowNoBreakSpace, + .wordJoiner, + .minusSign, + .objectReplacementCharacter, + ] + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StringStyle+Part.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StringStyle+Part.swift new file mode 100644 index 0000000..10039c8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StringStyle+Part.swift @@ -0,0 +1,302 @@ +// +// StringStyle+Part.swift +// BonMot +// +// Created by Brian King on 9/1/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +extension StringStyle { + + /// Each `Part` encapsulates one setting in a `StringStyle`. It is used + /// in a DSL for building `StringStyle` across BonMot. + public enum Part { + + case extraAttributes(StyleAttributes) + case font(BONFont) + case link(URL) + case backgroundColor(BONColor) + case color(BONColor) + case underline(NSUnderlineStyle, BONColor?) + case strikethrough(NSUnderlineStyle, BONColor?) + case baselineOffset(CGFloat) + + #if os(iOS) || os(tvOS) || os(watchOS) + + /// If set to `true`, when the string is read aloud, all punctuation will + /// be spoken aloud as well. + case speaksPunctuation(Bool) + + /// The BCP 47 language code that you would like the system to use when + /// reading this string aloud. A BCP 47 language code is generally of + /// the form “language-REGION”, e.g. “en-US”. You can see a [list of + /// languages and regions](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry) + /// and learn more about [BCP 47](https://www.rfc-editor.org/rfc/rfc5646.txt). + case speakingLanguage(String) + + /// The pitch of the voice used to read the text aloud. The range is + /// 0 to 2, where 0 is the lowest, 2 is the highest, and 1 is the default. + case speakingPitch(Double) + + /// The IPA pronunciation of the given range. + case speakingPronunciation(String) + + /// Whether the spoken text is queued behind, or interrupts, existing spoken content. + case shouldQueueSpeechAnnouncement(Bool) + + /// The accessibility heading level of the text. + case headingLevel(HeadingLevel) + #endif + + case ligatures(Ligatures) + + case alignment(NSTextAlignment) + case tracking(Tracking) + case lineSpacing(CGFloat) + case paragraphSpacingAfter(CGFloat) + case firstLineHeadIndent(CGFloat) + case headIndent(CGFloat) + case tailIndent(CGFloat) + case lineBreakMode(NSLineBreakMode) + case minimumLineHeight(CGFloat) + case maximumLineHeight(CGFloat) + case baseWritingDirection(NSWritingDirection) + case lineHeightMultiple(CGFloat) + case paragraphSpacingBefore(CGFloat) + + /// Values from 0 to 1 will result in varying levels of hyphenation, + /// with higher values resulting in more aggressive (i.e. more frequent) + /// hyphenation. + /// + /// Hyphenation is attempted when the ratio of the text width (as broken + /// without hyphenation) to the width of the line fragment is less than + /// the hyphenation factor. When the paragraph’s hyphenation factor is + /// 0.0, the layout manager’s hyphenation factor is used instead. When + /// both are 0.0, hyphenation is disabled. + case hyphenationFactor(Float) + + case xml + case xmlRules([XMLStyleRule]) + case xmlStyler(XMLStyler) + case transform(Transform) + #if os(iOS) || os(tvOS) || os(OSX) + case fontFeature(FontFeatureProvider) + + case numberSpacing(NumberSpacing) + case numberCase(NumberCase) + case fractions(Fractions) + + case superscript(Bool) + case `subscript`(Bool) + case ordinals(Bool) + case scientificInferiors(Bool) + + case smallCaps(SmallCaps) + + case stylisticAlternates(StylisticAlternates) + case contextualAlternates(ContextualAlternates) + #endif + #if os(iOS) || os(tvOS) + case textStyle(BonMotTextStyle) + #endif + #if os(iOS) || os(tvOS) + case adapt(AdaptiveStyle) + #endif + + case emphasis(Emphasis) + + // An advanced part that allows combining multiple parts as a single part + case style(StringStyle) + + } + + /// Create a `StringStyle` from zero or more `Part`s. + /// + /// - Parameter parts: Zero or more `Part`s + public init(_ parts: Part...) { + self.init(parts) + } + + /// Create a `StringStyle` from an array of parts + /// + /// - Parameter parts: An array of `StylePart`s + public init(_ parts: [Part]) { + self.init() + for part in parts { + update(part: part) + } + } + + /// Derive a new `StringStyle` based on this style, updated with zero or + /// more `Part`s. + /// + /// - Parameter parts: Zero or more `Part`s + /// - Returns: A newly configured `StringStyle` + public func byAdding(_ parts: Part...) -> StringStyle { + return byAdding(parts) + } + + /// Derive a new `StringStyle` based on this style, updated with zero or + /// more `Part`s. + /// + /// - Parameter parts: an array of `Part`s + /// - Returns: A newly configured `StringStyle` + public func byAdding(_ parts: [Part]) -> StringStyle { + var style = self + for part in parts { + style.update(part: part) + } + return style + } + + //swiftlint:disable function_body_length + //swiftlint:disable cyclomatic_complexity + /// Update the style with the specified style part. + /// + /// - Parameter stylePart: The style part with which to update the receiver. + mutating func update(part stylePart: Part) { + switch stylePart { + case let .extraAttributes(attributes): + self.extraAttributes = attributes + case let .font(font): + self.font = font + case let .link(link): + self.link = link + case let .backgroundColor(backgroundColor): + self.backgroundColor = backgroundColor + case let .color(color): + self.color = color + case let .underline(underline): + self.underline = underline + case let .strikethrough(strikethrough): + self.strikethrough = strikethrough + case let .baselineOffset(baselineOffset): + self.baselineOffset = baselineOffset + case let .ligatures(ligatures): + self.ligatures = ligatures + case let .alignment(alignment): + self.alignment = alignment + case let .tracking(tracking): + self.tracking = tracking + case let .lineSpacing(lineSpacing): + self.lineSpacing = lineSpacing + case let .paragraphSpacingAfter(paragraphSpacingAfter): + self.paragraphSpacingAfter = paragraphSpacingAfter + case let .firstLineHeadIndent(firstLineHeadIndent): + self.firstLineHeadIndent = firstLineHeadIndent + case let .headIndent(headIndent): + self.headIndent = headIndent + case let .tailIndent(tailIndent): + self.tailIndent = tailIndent + case let .lineBreakMode(lineBreakMode): + self.lineBreakMode = lineBreakMode + case let .minimumLineHeight(minimumLineHeight): + self.minimumLineHeight = minimumLineHeight + case let .maximumLineHeight(maximumLineHeight): + self.maximumLineHeight = maximumLineHeight + case let .baseWritingDirection(baseWritingDirection): + self.baseWritingDirection = baseWritingDirection + case let .lineHeightMultiple(lineHeightMultiple): + self.lineHeightMultiple = lineHeightMultiple + case let .paragraphSpacingBefore(paragraphSpacingBefore): + self.paragraphSpacingBefore = paragraphSpacingBefore + case .xml: + self.xmlStyler = NSAttributedString.defaultXMLStyler + case var .xmlRules(rules): + rules.append(contentsOf: Special.insertionRules) + self.xmlStyler = XMLStyleRule.Styler(rules: rules) + case let .xmlStyler(xmlStyler): + self.xmlStyler = xmlStyler + case let .transform(transform): + self.transform = transform + case let .style(style): + self.add(stringStyle: style) + case let .emphasis(emphasis): + self.emphasis = emphasis + default: + // interaction between `#if` and `switch` is disappointing. This case + // is in `default:` to remove a warning that default won't be accessed + // on some platforms. + switch stylePart { + case let .hyphenationFactor(hyphenationFactor): + self.hyphenationFactor = hyphenationFactor + default: + #if os(iOS) || os(tvOS) || os(watchOS) + switch stylePart { + case let .speaksPunctuation(speaksPunctuation): + self.speaksPunctuation = speaksPunctuation + return + case let .speakingLanguage(speakingLanguage): + self.speakingLanguage = speakingLanguage + return + case let .speakingPitch(speakingPitch): + self.speakingPitch = speakingPitch + return + case let .speakingPronunciation(speakingPronunciation): + self.speakingPronunciation = speakingPronunciation + return + case let .shouldQueueSpeechAnnouncement(shouldQueueSpeechAnnouncement): + self.shouldQueueSpeechAnnouncement = shouldQueueSpeechAnnouncement + return + case let .headingLevel(headingLevel): + self.headingLevel = headingLevel + return + default: + break + } + #endif + + #if os(OSX) || os(iOS) || os(tvOS) + switch stylePart { + case let .numberCase(numberCase): + self.numberCase = numberCase + case let .numberSpacing(numberSpacing): + self.numberSpacing = numberSpacing + case let .fractions(fractions): + self.fractions = fractions + case let .superscript(superscript): + self.superscript = superscript + case let .`subscript`(`subscript`): + self.`subscript` = `subscript` + case let .ordinals(ordinals): + self.ordinals = ordinals + case let .scientificInferiors(scientificInferiors): + self.scientificInferiors = scientificInferiors + case let .smallCaps(smallCaps): + self.smallCaps.insert(smallCaps) + case let .stylisticAlternates(stylisticAlternates): + self.stylisticAlternates.add(other: stylisticAlternates) + case let .contextualAlternates(contextualAlternates): + self.contextualAlternates.add(other: contextualAlternates) + case let .fontFeature(featureProvider): + self.fontFeatureProviders.append(featureProvider) + default: + #if os(iOS) || os(tvOS) + switch stylePart { + case let .adapt(style): + self.adaptations.append(style) + case let .textStyle(textStyle): + self.font = UIFont.bon_preferredFont(forTextStyle: textStyle, compatibleWith: nil) + default: + fatalError("StylePart \(stylePart) should have been caught by an earlier case.") + } + #else + fatalError("StylePart \(stylePart) should have been caught by an earlier case.") + #endif + } + #else + fatalError("StylePart \(stylePart) should have been caught by an earlier case.") + #endif + } + } + } + //swiftlint:enable function_body_length + //swiftlint:enable cyclomatic_complexity + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StringStyle.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StringStyle.swift new file mode 100644 index 0000000..d614f06 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StringStyle.swift @@ -0,0 +1,418 @@ +// +// StringStyle.swift +// BonMot +// +// Created by Brian King on 8/31/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// +// NOTE: Keep attributes in order to help reviewability. + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +/// The primary style container for BonMot, responsible for encapsulating any +/// attributes that are intended to be used with `NSAttributedString`. +public struct StringStyle { + + public var extraAttributes: StyleAttributes = [:] + public var font: BONFont? + public var link: URL? + public var backgroundColor: BONColor? + public var color: BONColor? + public var underline: (NSUnderlineStyle, BONColor?)? + public var strikethrough: (NSUnderlineStyle, BONColor?)? + public var baselineOffset: CGFloat? + + public var lineSpacing: CGFloat? + public var paragraphSpacingAfter: CGFloat? + public var alignment: NSTextAlignment? + public var firstLineHeadIndent: CGFloat? + public var headIndent: CGFloat? + public var tailIndent: CGFloat? + public var lineBreakMode: NSLineBreakMode? + public var minimumLineHeight: CGFloat? + public var maximumLineHeight: CGFloat? + public var baseWritingDirection: NSWritingDirection? + public var lineHeightMultiple: CGFloat? + public var paragraphSpacingBefore: CGFloat? + public var hyphenationFactor: Float? + + #if os(iOS) || os(tvOS) || os(watchOS) + public var speaksPunctuation: Bool? + public var speakingLanguage: String? + public var speakingPitch: Double? + public var speakingPronunciation: String? + public var shouldQueueSpeechAnnouncement: Bool? + public var headingLevel: HeadingLevel? + #endif + + public var ligatures: Ligatures? + + #if os(OSX) || os(iOS) || os(tvOS) + public var fontFeatureProviders: [FontFeatureProvider] = [] + + public var numberCase: NumberCase? + public var numberSpacing: NumberSpacing? + public var fractions: Fractions? + + public var superscript: Bool? + public var `subscript`: Bool? + public var ordinals: Bool? + public var scientificInferiors: Bool? + + public var smallCaps: Set = [] + + public var stylisticAlternates: StylisticAlternates = StylisticAlternates() + public var contextualAlternates: ContextualAlternates = ContextualAlternates() + #endif + #if os(iOS) || os(tvOS) + public var adaptations: [AdaptiveStyle] = [] + #endif + + public var emphasis: Emphasis? + public var tracking: Tracking? + public var xmlStyler: XMLStyler? + public var transform: Transform? + + public init() {} +} + +extension StringStyle { + + /// A `StyleAttributes` dictionary representing the current style. + public var attributes: StyleAttributes { + var theAttributes = extraAttributes + + theAttributes.update(possibleValue: font, forKey: .font) + theAttributes.update(possibleValue: link, forKey: .link) + theAttributes.update(possibleValue: backgroundColor, forKey: .backgroundColor) + theAttributes.update(possibleValue: color, forKey: .foregroundColor) + theAttributes.update(possibleValue: underline?.0.rawValue, forKey: .underlineStyle) + theAttributes.update(possibleValue: underline?.1, forKey: .underlineColor) + theAttributes.update(possibleValue: strikethrough?.0.rawValue, forKey: .strikethroughStyle) + theAttributes.update(possibleValue: strikethrough?.1, forKey: .strikethroughColor) + theAttributes.update(possibleValue: baselineOffset, forKey: .baselineOffset) + theAttributes.update(possibleValue: ligatures?.rawValue, forKey: .ligature) + + #if os(iOS) || os(tvOS) || os(watchOS) + theAttributes.update(possibleValue: speaksPunctuation, forKey: .accessibilitySpeechPunctuation) + theAttributes.update(possibleValue: speakingLanguage, forKey: .accessibilitySpeechLanguage) + theAttributes.update(possibleValue: speakingPitch, forKey: .accessibilitySpeechPitch) + if #available(iOS 11, tvOS 11, watchOS 4, *) { + theAttributes.update(possibleValue: speakingPronunciation, forKey: .accessibilitySpeechIPANotation) + theAttributes.update(possibleValue: shouldQueueSpeechAnnouncement as NSNumber?, forKey: .accessibilitySpeechQueueAnnouncement) + theAttributes.update(possibleValue: headingLevel?.rawValue as NSNumber?, forKey: .accessibilityTextHeadingLevel) + } + #endif + + let paragraph = StringStyle.paragraph(from: theAttributes) + paragraph.lineSpacing = lineSpacing ?? paragraph.lineSpacing + paragraph.paragraphSpacing = paragraphSpacingAfter ?? paragraph.paragraphSpacing + paragraph.alignment = alignment ?? paragraph.alignment + paragraph.firstLineHeadIndent = firstLineHeadIndent ?? paragraph.firstLineHeadIndent + paragraph.headIndent = headIndent ?? paragraph.headIndent + paragraph.tailIndent = tailIndent ?? paragraph.tailIndent + paragraph.lineBreakMode = lineBreakMode ?? paragraph.lineBreakMode + paragraph.minimumLineHeight = minimumLineHeight ?? paragraph.minimumLineHeight + paragraph.maximumLineHeight = maximumLineHeight ?? paragraph.maximumLineHeight + paragraph.baseWritingDirection = baseWritingDirection ?? paragraph.baseWritingDirection + paragraph.lineHeightMultiple = lineHeightMultiple ?? paragraph.lineHeightMultiple + paragraph.paragraphSpacingBefore = paragraphSpacingBefore ?? paragraph.paragraphSpacingBefore + paragraph.hyphenationFactor = hyphenationFactor ?? paragraph.hyphenationFactor + + if paragraph != NSParagraphStyle.default { + theAttributes.update(possibleValue: paragraph, forKey: .paragraphStyle) + } + + #if os(iOS) || os(tvOS) || os(OSX) + // Apply the features to the font present + let preFeaturedFont = theAttributes[.font] as? BONFont + var featureProviders = fontFeatureProviders + + featureProviders += [numberCase].compactMap { $0 } as [FontFeatureProvider] + featureProviders += [numberSpacing].compactMap { $0 } as [FontFeatureProvider] + featureProviders += [fractions].compactMap { $0 } as [FontFeatureProvider] + featureProviders += [superscript].compactMap { $0 }.map { ($0 ? VerticalPosition.superscript : VerticalPosition.normal) } as [FontFeatureProvider] + featureProviders += [`subscript`].compactMap { $0 }.map { ($0 ? VerticalPosition.`subscript` : VerticalPosition.normal) } as [FontFeatureProvider] + featureProviders += [ordinals].compactMap { $0 }.map { $0 ? VerticalPosition.ordinals : VerticalPosition.normal } as [FontFeatureProvider] + featureProviders += [scientificInferiors].compactMap { $0 }.map { $0 ? VerticalPosition.scientificInferiors : VerticalPosition.normal } as [FontFeatureProvider] + featureProviders += smallCaps.map { $0 as FontFeatureProvider } + featureProviders += [stylisticAlternates as FontFeatureProvider] + featureProviders += [contextualAlternates as FontFeatureProvider] + + let featuredFont = preFeaturedFont?.font(withFeatures: featureProviders) + theAttributes.update(possibleValue: featuredFont, forKey: .font) + #endif + + if let font = theAttributes[.font] as? BONFont, let emphasis = emphasis { + let descriptor = font.fontDescriptor + let existingTraits = descriptor.symbolicTraits + let newTraits = existingTraits.union(emphasis.symbolicTraits) + + // Explicit cast to optional because withSymbolicTraits returns an + // optional on Mac, but not on iOS. + let newDescriptor: BONFontDescriptor? = descriptor.withSymbolicTraits(newTraits) + if let newDesciptor = newDescriptor { + let newFont = BONFont(descriptor: newDesciptor, size: 0) + theAttributes.update(possibleValue: newFont, forKey: .font) + } + } + + #if os(iOS) || os(tvOS) + // Apply any adaptations + for adaptation in adaptations { + theAttributes = adaptation.embed(in: theAttributes) + } + #endif + + // Apply tracking + if let tracking = tracking { + let styledFont = theAttributes[.font] as? BONFont + theAttributes.update(possibleValue: tracking.kerning(for: styledFont), forKey: .kern) + #if os(iOS) || os(tvOS) + // Add the tracking as an adaptation + theAttributes = EmbeddedTransformationHelpers.embed(transformation: tracking, to: theAttributes) + #endif + } + + return theAttributes + } + + /// Create an `NSAttributedString` from the specified string. + /// - parameter from: The `String` to style. + /// - parameter existingAttributes: The existing attributes, if any, to use + /// as default values for the style. + /// + /// - returns: A new `NSAttributedString` + public func attributedString(from theString: String, existingAttributes: StyleAttributes? = nil) -> NSAttributedString { + if let xmlStyler = xmlStyler { + let builder = XMLBuilder( + string: theString, + styler: xmlStyler, + options: [], + baseStyle: self + ) + if let attributedString = try? builder.parseAttributedString() { + return attributedString + } + } + let tagsApplied = NSAttributedString(string: theString, attributes: supplyDefaults(for: existingAttributes)) + + guard let transform = transform else { + return tagsApplied + } + + let mutable = tagsApplied.mutableStringCopy() + let fullRange = NSRange(location: 0, length: mutable.length) + mutable.enumerateAttributes(in: fullRange, options: [], using: { (_, range, _) in + let substring = mutable.attributedSubstring(from: range).string + let transformed = transform.transformer(substring) + mutable.replaceCharacters(in: range, with: transformed) + }) + + return mutable + } + +} + +extension StringStyle { + + /// Update the `extraAttributes` in the style object. This is used to + /// provide the default values configured in UI elements, which the style + /// can override. + /// + /// - parameter extraAttributes: The attributes to add to the style before + /// applying the other properties. + public mutating func add(extraAttributes attributes: StyleAttributes) { + for (key, value) in attributes { + extraAttributes[key] = value + } + } + + /// Update the receiver with values specified in `stringStyle`. Any value + /// configured in `stringStyle` will overwrite the values specified in the + /// receiver. + /// + /// - parameter stringStyle: The style with which to update this style. + public mutating func add(stringStyle theStringStyle: StringStyle) { + add(extraAttributes: theStringStyle.extraAttributes) + font = theStringStyle.font ?? font + link = theStringStyle.link ?? link + backgroundColor = theStringStyle.backgroundColor ?? backgroundColor + color = theStringStyle.color ?? color + underline = theStringStyle.underline ?? underline + strikethrough = theStringStyle.strikethrough ?? strikethrough + baselineOffset = theStringStyle.baselineOffset ?? baselineOffset + + ligatures = theStringStyle.ligatures ?? ligatures + + #if os(iOS) || os(tvOS) || os(watchOS) + speaksPunctuation = theStringStyle.speaksPunctuation ?? speaksPunctuation + speakingLanguage = theStringStyle.speakingLanguage ?? speakingLanguage + speakingPitch = theStringStyle.speakingPitch ?? speakingPitch + if #available(iOS 11, tvOS 11, watchOS 4, *) { + speakingPronunciation = theStringStyle.speakingPronunciation ?? speakingPronunciation + shouldQueueSpeechAnnouncement = theStringStyle.shouldQueueSpeechAnnouncement ?? shouldQueueSpeechAnnouncement + headingLevel = theStringStyle.headingLevel ?? headingLevel + } + #endif + + lineSpacing = theStringStyle.lineSpacing ?? lineSpacing + paragraphSpacingAfter = theStringStyle.paragraphSpacingAfter ?? paragraphSpacingAfter + alignment = theStringStyle.alignment ?? alignment + firstLineHeadIndent = theStringStyle.firstLineHeadIndent ?? firstLineHeadIndent + headIndent = theStringStyle.headIndent ?? headIndent + tailIndent = theStringStyle.tailIndent ?? tailIndent + lineBreakMode = theStringStyle.lineBreakMode ?? lineBreakMode + minimumLineHeight = theStringStyle.minimumLineHeight ?? minimumLineHeight + maximumLineHeight = theStringStyle.maximumLineHeight ?? maximumLineHeight + baseWritingDirection = theStringStyle.baseWritingDirection ?? baseWritingDirection + lineHeightMultiple = theStringStyle.lineHeightMultiple ?? lineHeightMultiple + paragraphSpacingBefore = theStringStyle.paragraphSpacingBefore ?? paragraphSpacingBefore + hyphenationFactor = theStringStyle.hyphenationFactor ?? hyphenationFactor + + #if os(iOS) || os(tvOS) || os(OSX) + fontFeatureProviders.append(contentsOf: theStringStyle.fontFeatureProviders) + + numberCase = theStringStyle.numberCase ?? numberCase + numberSpacing = theStringStyle.numberSpacing ?? numberSpacing + fractions = theStringStyle.fractions ?? fractions + + superscript = theStringStyle.superscript ?? superscript + `subscript` = theStringStyle.`subscript` ?? `subscript` + ordinals = theStringStyle.ordinals ?? ordinals + scientificInferiors = theStringStyle.scientificInferiors ?? scientificInferiors + + smallCaps = theStringStyle.smallCaps.isEmpty ? smallCaps : theStringStyle.smallCaps + + stylisticAlternates.add(other: theStringStyle.stylisticAlternates) + contextualAlternates.add(other: theStringStyle.contextualAlternates) + #endif + + if let newEmphasis = theStringStyle.emphasis, let existingEmphasis = emphasis { + // If we have both new and existing, merge them + emphasis = existingEmphasis.union(newEmphasis) + } + else if let newEmphasis = theStringStyle.emphasis { + // If we have only new, just replace existing + emphasis = newEmphasis + } + + #if os(iOS) || os(tvOS) + adaptations.append(contentsOf: theStringStyle.adaptations) + #endif + tracking = theStringStyle.tracking ?? tracking + xmlStyler = theStringStyle.xmlStyler ?? xmlStyler + transform = theStringStyle.transform ?? transform + } + + public func byAdding(stringStyle style: StringStyle) -> StringStyle { + var newStyle = self + newStyle.add(stringStyle: style) + return newStyle + } + +} + +public extension StringStyle { + + /// Supply the receiver's attributes as default values for the passed + /// `StyleAttributes` dictionary. This will also perform some merging of + /// values. This includes `NSParagraphStyle` and the receiver's attributes. + /// + /// - parameter for: The object with which to overwrite the defaults. + /// - returns: The new attributes + func supplyDefaults(for attributes: StyleAttributes?) -> StyleAttributes { + guard var attributes = attributes else { + return self.attributes + } + for (key, value) in self.attributes { + switch (key, value, attributes[key]) { + case (.paragraphStyle, let paragraph as NSParagraphStyle, let otherParagraph as NSParagraphStyle): + attributes[.paragraphStyle] = paragraph.supplyDefaults(for: otherParagraph) + case (BonMotTransformationsAttributeName, + var transformations as [Any], + let otherTransformations as [Any]): + transformations.append(contentsOf: otherTransformations) + attributes[BonMotTransformationsAttributeName] = transformations + case let (key, value, nil): + attributes.update(possibleValue: value, forKey: key) + default: + break + } + } + return attributes + } + + /// A helper to extract an `NSMutableParagraphStyle` from a value in an + /// attributes dictionary. + /// - parameter from: the attributes dictionary from which to extract the + /// paragraph style. + /// - returns: A mutable copy of an `NSParagraphStyle`, or a new + /// `NSMutableParagraphStyle` if the value is `nil`. + static func paragraph(from styleAttributes: StyleAttributes) -> NSMutableParagraphStyle { + let theObject = styleAttributes[.paragraphStyle] + let result: NSMutableParagraphStyle + if let paragraphStyle = theObject as? NSMutableParagraphStyle { + result = paragraphStyle + } + else if let paragraphStyle = theObject as? NSParagraphStyle { + result = paragraphStyle.mutableParagraphStyleCopy() + } + else { + result = NSMutableParagraphStyle() + } + return result + } + + } + +extension NSParagraphStyle { + + //swiftlint:disable cyclomatic_complexity + /// Update the passed `NSParagraphStyle`'s properties with the value in this + /// the receiver (only if the supplied `NSParagraphStyle`'s value for a + /// given property is the default value). + /// + /// - Parameter paragraphStyle: The paragraph style to update. + /// - Returns: The updated paragraph style. + func supplyDefaults(for paragraphStyle: NSParagraphStyle) -> NSParagraphStyle { + let defaults = NSParagraphStyle.default + let paragraph = paragraphStyle.mutableParagraphStyleCopy() + if paragraph.lineSpacing == defaults.lineSpacing { paragraph.lineSpacing = lineSpacing } + if paragraph.paragraphSpacing == defaults.paragraphSpacing { paragraph.paragraphSpacing = paragraphSpacing } + if paragraph.alignment == defaults.alignment { paragraph.alignment = alignment } + if paragraph.firstLineHeadIndent == defaults.firstLineHeadIndent { paragraph.firstLineHeadIndent = firstLineHeadIndent } + if paragraph.headIndent == defaults.headIndent { paragraph.headIndent = headIndent } + if paragraph.tailIndent == defaults.tailIndent { paragraph.tailIndent = tailIndent } + if paragraph.lineBreakMode == defaults.lineBreakMode { paragraph.lineBreakMode = lineBreakMode } + if paragraph.minimumLineHeight == defaults.minimumLineHeight { paragraph.minimumLineHeight = minimumLineHeight } + if paragraph.maximumLineHeight == defaults.maximumLineHeight { paragraph.maximumLineHeight = maximumLineHeight } + if paragraph.baseWritingDirection == defaults.baseWritingDirection { paragraph.baseWritingDirection = baseWritingDirection } + if paragraph.lineHeightMultiple == defaults.lineHeightMultiple { paragraph.lineHeightMultiple = lineHeightMultiple } + if paragraph.paragraphSpacingBefore == defaults.paragraphSpacingBefore { paragraph.paragraphSpacingBefore = paragraphSpacingBefore } + if paragraph.hyphenationFactor == defaults.hyphenationFactor { paragraph.hyphenationFactor = hyphenationFactor } + if paragraph.tabStops == defaults.tabStops { paragraph.tabStops = tabStops } + return paragraph + } + //swiftlint:enable cyclomatic_complexity + +} + +extension Dictionary { + + /// Set a given value in a `Dictionary`, but only if that value is non-nil. + /// + /// - Parameters: + /// - value: The new value to insert into the dictionary if it is non-nil. + /// - key: The key for which to set the value. + internal mutating func update(possibleValue value: Value?, forKey key: Key) { + if let value = value { + self[key] = value + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StylisticAlternates.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StylisticAlternates.swift new file mode 100644 index 0000000..6f51da5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/StylisticAlternates.swift @@ -0,0 +1,285 @@ +// +// StylisticAlternates.swift +// BonMot +// +// Created by Zev Eisenberg on 11/4/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +// This is not supported on watchOS +#if os(iOS) || os(tvOS) || os(OSX) + + /// Different stylistic alternates available for customizing a font. + /// Typically, a font will support a small subset of these alternates, and + /// what they mean in a particular font is up to the font's creator. For + /// example, in Apple's San Francisco font, turn on alternate set "six" to + /// enable high-legibility alternates for ambiguous characters like: 0lI164. + public struct StylisticAlternates { + + var one: Bool? + var two: Bool? + var three: Bool? + var four: Bool? + var five: Bool? + var six: Bool? + var seven: Bool? + var eight: Bool? + var nine: Bool? + var ten: Bool? + var eleven: Bool? + var twelve: Bool? + var thirteen: Bool? + var fourteen: Bool? + var fifteen: Bool? + var sixteen: Bool? + var seventeen: Bool? + var eighteen: Bool? + var nineteen: Bool? + var twenty: Bool? + + public init() { } + + } + + // Convenience constructors + extension StylisticAlternates { + + public static func one(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.one = isOn + return alts + } + + public static func two(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.two = isOn + return alts + } + + public static func three(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.three = isOn + return alts + } + + public static func four(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.four = isOn + return alts + } + + public static func five(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.five = isOn + return alts + } + + public static func six(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.six = isOn + return alts + } + + public static func seven(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.seven = isOn + return alts + } + + public static func eight(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.eight = isOn + return alts + } + + public static func nine(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.nine = isOn + return alts + } + + public static func ten(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.ten = isOn + return alts + } + + public static func eleven(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.eleven = isOn + return alts + } + + public static func twelve(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.twelve = isOn + return alts + } + + public static func thirteen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.thirteen = isOn + return alts + } + + public static func fourteen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.fourteen = isOn + return alts + } + + public static func fifteen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.fifteen = isOn + return alts + } + + public static func sixteen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.sixteen = isOn + return alts + } + + public static func seventeen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.seventeen = isOn + return alts + } + + public static func eighteen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.eighteen = isOn + return alts + } + + public static func nineteen(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.nineteen = isOn + return alts + } + + public static func twenty(on isOn: Bool) -> StylisticAlternates { + var alts = StylisticAlternates() + alts.twenty = isOn + return alts + } + + } + + extension StylisticAlternates { + + mutating public func add(other theOther: StylisticAlternates) { + // swiftlint:disable operator_usage_whitespace + one = theOther.one ?? one + two = theOther.two ?? two + three = theOther.three ?? three + four = theOther.four ?? four + five = theOther.five ?? five + six = theOther.six ?? six + seven = theOther.seven ?? seven + eight = theOther.eight ?? eight + nine = theOther.nine ?? nine + ten = theOther.ten ?? ten + eleven = theOther.eleven ?? eleven + twelve = theOther.twelve ?? twelve + thirteen = theOther.thirteen ?? thirteen + fourteen = theOther.fourteen ?? fourteen + fifteen = theOther.fifteen ?? fifteen + sixteen = theOther.sixteen ?? sixteen + seventeen = theOther.seventeen ?? seventeen + eighteen = theOther.eighteen ?? eighteen + nineteen = theOther.nineteen ?? nineteen + twenty = theOther.twenty ?? twenty + // swiftlint:enable operator_usage_whitespace + } + + public func byAdding(other theOther: StylisticAlternates) -> StylisticAlternates { + var varSelf = self + varSelf.add(other: theOther) + return varSelf + } + + } + + extension StylisticAlternates: FontFeatureProvider { + + //swiftlint:disable:next cyclomatic_complexity + public func featureSettings() -> [(type: Int, selector: Int)] { + var selectors = [Int]() + + if let one = one { + selectors.append(one ? kStylisticAltOneOnSelector : kStylisticAltOneOffSelector) + } + if let two = two { + selectors.append(two ? kStylisticAltTwoOnSelector : kStylisticAltTwoOffSelector) + } + if let three = three { + selectors.append(three ? kStylisticAltThreeOnSelector : kStylisticAltThreeOffSelector) + } + if let four = four { + selectors.append(four ? kStylisticAltFourOnSelector : kStylisticAltFourOffSelector) + } + if let five = five { + selectors.append(five ? kStylisticAltFiveOnSelector : kStylisticAltFiveOffSelector) + } + if let six = six { + selectors.append(six ? kStylisticAltSixOnSelector : kStylisticAltSixOffSelector) + } + if let seven = seven { + selectors.append(seven ? kStylisticAltSevenOnSelector : kStylisticAltSevenOffSelector) + } + if let eight = eight { + selectors.append(eight ? kStylisticAltEightOnSelector : kStylisticAltEightOffSelector) + } + if let nine = nine { + selectors.append(nine ? kStylisticAltNineOnSelector : kStylisticAltNineOffSelector) + } + if let ten = ten { + selectors.append(ten ? kStylisticAltTenOnSelector : kStylisticAltTenOffSelector) + } + if let eleven = eleven { + selectors.append(eleven ? kStylisticAltElevenOnSelector : kStylisticAltElevenOffSelector) + } + if let twelve = twelve { + selectors.append(twelve ? kStylisticAltTwelveOnSelector : kStylisticAltTwelveOffSelector) + } + if let thirteen = thirteen { + selectors.append(thirteen ? kStylisticAltThirteenOnSelector : kStylisticAltThirteenOffSelector) + } + if let fourteen = fourteen { + selectors.append(fourteen ? kStylisticAltFourteenOnSelector : kStylisticAltFourteenOffSelector) + } + if let fifteen = fifteen { + selectors.append(fifteen ? kStylisticAltFifteenOnSelector : kStylisticAltFifteenOffSelector) + } + if let sixteen = sixteen { + selectors.append(sixteen ? kStylisticAltSixteenOnSelector : kStylisticAltSixteenOffSelector) + } + if let seventeen = seventeen { + selectors.append(seventeen ? kStylisticAltSeventeenOnSelector : kStylisticAltSeventeenOffSelector) + } + if let eighteen = eighteen { + selectors.append(eighteen ? kStylisticAltEighteenOnSelector : kStylisticAltEighteenOffSelector) + } + if let nineteen = nineteen { + selectors.append(nineteen ? kStylisticAltNineteenOnSelector : kStylisticAltNineteenOffSelector) + } + if let twenty = twenty { + selectors.append(twenty ? kStylisticAltTwentyOnSelector : kStylisticAltTwentyOffSelector) + } + + return selectors.map { (type: kStylisticAlternativesType, selector: $0) } + } + + } + + public func + (lhs: StylisticAlternates, rhs: StylisticAlternates) -> StylisticAlternates { + return lhs.byAdding(other: rhs) + } +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Tab.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Tab.swift new file mode 100644 index 0000000..067ce0e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Tab.swift @@ -0,0 +1,138 @@ +// +// Tab.swift +// BonMot +// +// Created by Brian King on 9/28/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +/// Creates a tab (\t) character with a calculated space from the beginning of the line. +public enum Tab { + + /// A spacer `Tab` introduces a tab of the specified amount from the current + /// position in the `String`, much like tab stops in a word processor. + case spacer(CGFloat) + + /// A head indent `Tab` will introduce a tab of the specified amount from + /// the current position in the string, and update the `headIndent` value in + /// the containing `NSParagraphStyle`. + case headIndent(CGFloat) + +} + +extension Tab: Composable { + + public func append(to attributedString: NSMutableAttributedString, baseStyle: StringStyle, isLastElement: Bool) { + let attributes = baseStyle.attributes + #if os(iOS) + // Embed the tab in the attributes + let tabAttributes = EmbeddedTransformationHelpers.embed(transformation: self, to: attributes) + #else + let tabAttributes: StyleAttributes = attributes + #endif + let tabRange = NSRange(location: attributedString.length, length: 1) + + attributedString.append(NSAttributedString(string: Special.tab.description, attributes: tabAttributes)) + + // Calculate the tab spacing + update(string: attributedString, in: tabRange) + } + +} + +extension Tab { + + /// Update the tab calculation for the tabs in `range`. This will create an + /// `NSTabStop` in the paragraph style with the specified padding from the + /// beginning of the line. This supports multiple tabs in one line and + /// multiple lines. + /// + /// This implementation conforms to `AttributedStringTransformation`, but + /// since this is used when the adaptive code may not be included, the + /// conformance is not declared here. It is declared in Tab+Adaptive.swift. + /// + /// - Parameters: + /// - attributedString: The attributed string to update. + /// - range: The range on which to perform the tab calculations. + func update(string attributedString: NSMutableAttributedString, in range: NSRange) { + let string = attributedString.string as NSString + + // Lookup the range this paragraph is operating on. + // This is the range from `range` to the preceeding newline or the start of the string. + let precedingRange = NSRange(location: 0, length: NSMaxRange(range)) + var leadingNewline = string.rangeOfCharacter(from: CharacterSet.newlines, options: [.backwards], range: precedingRange).location + leadingNewline = (leadingNewline == NSNotFound) ? 0 : leadingNewline + 1 + let paragraphRange = NSRange(location: leadingNewline, length: NSMaxRange(range) - leadingNewline) + + // Search backwards by attribute cluster to obtain the paragraph inside of `paragraphRange`. + var paragraphCursor = range.location + var paragraphAttribute: Any? + while paragraphCursor >= leadingNewline && paragraphAttribute == nil { + var attributeRange = NSRange() + let attributes = attributedString.attributes(at: paragraphCursor, effectiveRange: &attributeRange) + paragraphAttribute = attributes[.paragraphStyle] + paragraphCursor = attributeRange.location - 1 + } + + // Prepare the NSMutableParagraphStyle and configure it over the paragraphRange + let paragraph: NSMutableParagraphStyle + if paragraphAttribute == nil { + paragraph = NSMutableParagraphStyle() + } + else if let existingParagraph = paragraphAttribute as? NSMutableParagraphStyle { + paragraph = existingParagraph + } + else if let existingParagraph = paragraphAttribute as? NSParagraphStyle { + paragraph = existingParagraph.mutableParagraphStyleCopy() + } + else { + fatalError("Non paragraphStyle held in NSParagraphStyleAttributeName.") + } + + // Enumerate tabs over the range of the paragraph, keeping count of the tabs. + var enumerationRange = paragraphRange + var tabIndex = 0 + while true { + let tabRange = string.range(of: "\t", options: [], range: enumerationRange) + guard tabRange.location != NSNotFound else { break } + + // If the tab is in `range`, recalculate the tab at tabIndex. + if NSLocationInRange(tabRange.location, range) { + + // Calculate the length of the string before the tab. Since tabs are relative to the paragraph range, + // start at the start of the effective range for NSParagraphStyleAttributeName + let preTab = attributedString.attributedSubstring(from: NSRange(location: paragraphRange.location, length: tabRange.location - paragraphRange.location)) + let max = CGSize(width: CGFloat.greatestFiniteMagnitude, height: .greatestFiniteMagnitude) + let contentWidth = preTab.boundingRect(with: max, options: .usesLineFragmentOrigin, context: nil).width + + // Add the padding and update the NSTextTab at tabIndex. + let tabStop = contentWidth + padding + paragraph.tabStops[tabIndex] = NSTextTab(textAlignment: .natural, location: tabStop, options: [:]) + + // Update the paragraph object if it is a headIndent tab. + if case .headIndent = self { + paragraph.headIndent = tabStop + } + } + // Update the enumerationRange and tabIndex for the next pass + enumerationRange.length = NSMaxRange(enumerationRange) - NSMaxRange(tabRange) + enumerationRange.location = NSMaxRange(tabRange) + tabIndex += 1 + } + attributedString.addAttribute(.paragraphStyle, value: paragraph, range: paragraphRange) + } + + var padding: CGFloat { + switch self { + case let .spacer(padding): return padding + case let .headIndent(padding): return padding + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Tracking.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Tracking.swift new file mode 100644 index 0000000..a4713d5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Tracking.swift @@ -0,0 +1,31 @@ +// +// Tracking.swift +// BonMot +// +// Created by Brian King on 9/26/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import CoreGraphics + +/// An enumeration representing the tracking to be applied. +public enum Tracking { + + case point(CGFloat) + case adobe(CGFloat) + + public func kerning(for font: BONFont?) -> CGFloat { + switch self { + case .point(let kernValue): + return kernValue + case .adobe(let adobeTracking): + let AdobeTrackingDivisor: CGFloat = 1000.0 + if font == nil { + print("Can not apply tracking to style when no font is defined, using 0 instead") + } + let pointSize = font?.pointSize ?? 0 + return pointSize * (adobeTracking / AdobeTrackingDivisor) + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Transform.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Transform.swift new file mode 100644 index 0000000..bb2be90 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/Transform.swift @@ -0,0 +1,42 @@ +// +// Transform.swift +// BonMot +// +// Created by Zev Eisenberg on 3/24/17. +// Copyright © 2017 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +public enum Transform { + + public typealias TransformFunction = (String) -> String + + case lowercase + case uppercase + case capitalized + + case lowercaseWithLocale(Locale) + case uppercaseWithLocale(Locale) + case capitalizedWithLocale(Locale) + case custom(TransformFunction) + + var transformer: TransformFunction { + switch self { + case .lowercase: return { string in string.localizedLowercase } + case .uppercase: return { string in string.localizedUppercase } + case .capitalized: return { string in string.localizedCapitalized } + + case .lowercaseWithLocale(let locale): return { string in string.lowercased(with: locale) } + case .uppercaseWithLocale(let locale): return { string in string.uppercased(with: locale) } + case .capitalizedWithLocale(let locale): return { string in string.capitalized(with: locale) } + + case .custom(let transform): return transform + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptableTextContainer.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptableTextContainer.swift new file mode 100644 index 0000000..6232fc7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptableTextContainer.swift @@ -0,0 +1,288 @@ +// +// AdaptableTextContainer.swift +// BonMot +// +// Created by Brian King on 7/19/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import UIKit + +/// A protocol to update the text style contained by the object. This can be +/// triggered manually in `traitCollectionDidChange(_:)`. Any `UIViewController` +/// or `UIView` that conforms to this protocol will be informed of content size +/// category changes if `UIApplication.enableAdaptiveContentSizeMonitor()` is called. +/// - Note: We don't conform UI elements to this protocol due to a [bug in Xcode](http://www.openradar.me/30001713). +/// The protocol still exists as a container for selectors. +@objc(BONAdaptableTextContainer) +public protocol AdaptableTextContainer { + + /// Update the text style contained by the object in response to a trait + /// collection change. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + func adaptText(forTraitCollection traitCollection: UITraitCollection) + +} + +// MARK: - AdaptableTextContainer for UILabel +extension UILabel { + + /// Adapt `attributedText` to the specified trait collection. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + + // Update the font, then the attributed string. If the font doesn't keep in sync when + // not using attributedText, weird things happen so update it first. + // See UIKitTests.testLabelFontPropertyBehavior for interesting behavior. + + if let bonMotStyle = bonMotStyle { + let attributes = NSAttributedString.adapt(attributes: bonMotStyle.attributes, to: traitCollection) + font = attributes[.font] as? BONFont + } + if let attributedText = attributedText { + self.attributedText = attributedText.adapted(to: traitCollection) + } + } + +} + +// MARK: - AdaptableTextContainer for UITextView +extension UITextView { + + /// Adapt `attributedText` and `typingAttributes` to the specified trait collection. + /// + /// - parameter traitCollection: The updated trait collection + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + if let attributedText = attributedText { + self.attributedText = attributedText.adapted(to: traitCollection) + } + #if swift(>=4.2) + typingAttributes = NSAttributedString.adapt(attributes: typingAttributes, to: traitCollection) + #else + typingAttributes = NSAttributedString.adapt(attributes: typingAttributes.withTypedKeys(), to: traitCollection).withStringKeys + #endif + } + +} + +// MARK: - AdaptableTextContainer for UITextField +extension UITextField { + + /// Adapt `attributedText`, `attributedPlaceholder`, and + /// `defaultTextAttributes` to the specified trait collection. + /// + /// - note: Do not modify `typingAttributes`, as they are relevant only + /// while the text field has first responder status, and they are + /// reset as new text is entered. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + if let attributedText = attributedText?.adapted(to: traitCollection) { + if attributedText.length > 0 { + font = attributedText.attribute(.font, at: 0, effectiveRange: nil) as? UIFont + } + self.attributedText = attributedText + } + if let attributedPlaceholder = attributedPlaceholder { + self.attributedPlaceholder = attributedPlaceholder.adapted(to: traitCollection) + } + #if swift(>=4.2) + defaultTextAttributes = NSAttributedString.adapt(attributes: defaultTextAttributes, to: traitCollection) + #else + defaultTextAttributes = NSAttributedString.adapt(attributes: defaultTextAttributes.withTypedKeys(), to: traitCollection).withStringKeys + #endif + // Fix an issue where shrinking or growing text would stay the same width, but add whitespace. + setNeedsDisplay() + } + +} + +// Extension is here to work around [SR-631](https://bugs.swift.org/browse/SR-631), +// which requires new types declared in extensions to be built before they can +// themselves be extended. This is fixed in Xcode 10, so we can revert this when +// we stop supporting Xcode 9. (Another workaround is to reorder the files in +// the Compile Sources build phase, but since this is a library, we do not own +// that build phase in all projects that we are used in. We could have renamed +// Compatibility.swift to _Compatibility.swift and trusted CocoaPods to sort +// built files alphabetically, but we're opting to use the more reliable method +// of just putting the extension in the file where it's used. + +#if os(iOS) || os(tvOS) + #if swift(>=4.2) + #else + extension UIControl { + + typealias State = UIControlState + + } + #endif +#endif + +// MARK: - AdaptableTextContainer for UIButton +extension UIButton { + + /// Adapt `attributedTitle`, for all control states, to the specified trait collection. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + for state in UIControl.State.commonStates { + let attributedText = attributedTitle(for: state)?.adapted(to: traitCollection) + setAttributedTitle(attributedText, for: state) + } + } + +} + +// MARK: - AdaptableTextContainer for UISegmentedControl +extension UISegmentedControl { + + // `UISegmentedControl` has terrible generics ([NSObject: AnyObject]? or [AnyHashable: Any]?) on + /// `titleTextAttributes`, so use a helper in Swift 3+ + @nonobjc final func bon_titleTextAttributes(for state: UIControl.State) -> StyleAttributes { + let attributes = titleTextAttributes(for: state) ?? [:] + var result: StyleAttributes = [:] + for value in attributes { + #if swift(>=4.2) + result[value.key] = value + #else + guard let string = value.key as? StyleAttributes.Key else { + fatalError("Can not convert key \(value.key) to String") + } + result[string] = value + #endif + } + return result + } + + /// Adapt `attributedTitle`, for all control states, to the specified trait collection. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + for state in UIControl.State.commonStates { + let attributes = bon_titleTextAttributes(for: state) + let newAttributes = NSAttributedString.adapt(attributes: attributes, to: traitCollection) + setTitleTextAttributes(newAttributes, for: state) + } + } + +} + +// MARK: - AdaptableTextContainer for UINavigationBar +extension UINavigationBar { + + /// Adapt `titleTextAttributes` to the specified trait collection. + /// + /// - note: This does not update the bar button items. These should be + /// updated by the containing view controller. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + if let titleTextAttributes = titleTextAttributes { + self.titleTextAttributes = NSAttributedString.adapt(attributes: titleTextAttributes, to: traitCollection) + } + } + +} + +#if os(tvOS) +#else +// MARK: - AdaptableTextContainer for UIToolbar +extension UIToolbar { + + /// Adapt all bar items's attributed text to the specified trait collection. + /// + /// - note: This will update only bar items that are contained on the screen + /// at the time that it is called. + /// + /// - parameter traitCollection: The updated trait collection + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + for item in items ?? [] { + item.adaptText(forTraitCollection: traitCollection) + } + } + +} +#endif + +// MARK: - AdaptableTextContainer for UIViewController +extension UIViewController { + + /// Adapt the attributed text of teh bar items in the navigation item or in + /// the toolbar to the specified trait collection. + /// + /// - parameter traitCollection: The new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + for item in navigationItem.allBarItems { + item.adaptText(forTraitCollection: traitCollection) + } + #if os(tvOS) + #else + for item in toolbarItems ?? [] { + item.adaptText(forTraitCollection: traitCollection) + } + if let backBarButtonItem = navigationItem.backBarButtonItem { + backBarButtonItem.adaptText(forTraitCollection: traitCollection) + } + #endif + } + +} + +// MARK: - AdaptableTextContainer for UIBarItem +extension UIBarItem { + + /// Adapt `titleTextAttributes` to the specified trait collection. + /// + /// - note: This extension does not conform to `AdaptableTextContainer` + /// because `UIBarIterm` is not a view or view controller. + /// - parameter traitCollection: the new trait collection. + @objc(bon_updateTextForTraitCollection:) + public func adaptText(forTraitCollection traitCollection: UITraitCollection) { + for state in UIControl.State.commonStates { + let attributes = titleTextAttributes(for: state) ?? [:] + #if swift(>=4.2) + let newAttributes = NSAttributedString.adapt(attributes: attributes, to: traitCollection) + setTitleTextAttributes(newAttributes, for: state) + #else + let newAttributes = NSAttributedString.adapt(attributes: attributes.withTypedKeys(), to: traitCollection) + setTitleTextAttributes(newAttributes, for: state) + #endif + } + } + +} + +extension UIControl.State { + + /// The most common states that are used in apps. Using this defined set of + /// attributes is far simpler than trying to build a system that will + /// iterate through only the permutations that are currently configured. If + /// you use a valid `UIControlState` in your app that is not represented + /// here, please open a pull request to add it. + @nonobjc static var commonStates: [UIControl.State] { + return [.normal, .highlighted, .disabled, .selected, [.highlighted, .selected]] + } + +} + +extension UINavigationItem { + + /// Convenience getter comprising `leftBarButtonItems` and `rightBarButtonItems`. + final var allBarItems: [UIBarButtonItem] { + var allBarItems = leftBarButtonItems ?? [] + allBarItems.append(contentsOf: rightBarButtonItems ?? []) + return allBarItems + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptiveStyle.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptiveStyle.swift new file mode 100644 index 0000000..12dcc96 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptiveStyle.swift @@ -0,0 +1,202 @@ +// +// AdaptiveStyle.swift +// BonMot +// +// Created by Brian King on 8/31/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import UIKit + +/// A few default font scaling behaviors. +public enum AdaptiveStyle { + + /// Scale the font up or down based on the Dynamic Type slider, but do not + /// grow into the Accessibility ranges. + case control + + /// Scale the font up or down based on the Dynamic Type slider, + /// including Accessibility sizes. + case body + + /// Enable automatic scaling of fonts obtained using the `preferredFont(…)` + /// family of methods. + case preferred + + /// If the text is scaled above `size`, substitute the font named + /// `useFontNamed`, but using all the same attributes as the original font. + /// This style may be combined with other scaling behaviors such as `control` + /// and `body`. + case above(size: CGFloat, useFontNamed: String) + + /// If the text is scaled below `size`, substitute the font named + /// `useFontNamed`, but using all the same attributes as the original font. + /// This style may be combined with other scaling behaviors such as `control` + /// and `body`. + case below(size: CGFloat, useFontNamed: String) + +} + +extension AdaptiveStyle: AdaptiveStyleTransformation { + + enum AttributeName { + + static let nonAdaptedFont = NSAttributedString.Key("BonMotNonAdaptedFont") + + } + + func embed(in attributes: StyleAttributes) -> StyleAttributes { + guard let font = attributes[.font] as? BONFont else { + print("No font to adapt, ignoring adaptive style") + return attributes + } + var attributes = attributes + attributes[AttributeName.nonAdaptedFont] = font + attributes = EmbeddedTransformationHelpers.embed(transformation: self, to: attributes) + return attributes + } + + func adapt(attributes theAttributes: StyleAttributes, to traitCollection: UITraitCollection) -> StyleAttributes? { + guard var font = theAttributes[AttributeName.nonAdaptedFont] as? BONFont else { + fatalError("The designated font is set when the adaptive style is added") + } + let pointSize = font.pointSize + let contentSizeCategory = traitCollection.bon_preferredContentSizeCategory + var styleAttributes = theAttributes + switch self { + case .control: + font = UIFont(descriptor: font.fontDescriptor, size: AdaptiveStyle.adapt(designatedSize: pointSize, for: contentSizeCategory)) + case .body: + font = UIFont(descriptor: font.fontDescriptor, size: AdaptiveStyle.adaptBody(designatedSize: pointSize, for: contentSizeCategory)) + case .preferred: + if let textStyle = font.textStyle { + font = UIFont.bon_preferredFont(forTextStyle: textStyle, compatibleWith: traitCollection) + } + else { + print("No text style in the font, can not adapt") + } + case .above(let size, let fontName): + font = pointSize > size ? font.fontWithSameAttributes(named: fontName) : font + case .below(let size, let family): + font = pointSize < size ? font.fontWithSameAttributes(named: family) : font + } + styleAttributes[.font] = font + return styleAttributes + } + +} + +extension AdaptiveStyle { + + /// The font size adjustment to use for each content size category. + static var shiftTable: [BonMotContentSizeCategory: CGFloat] { + return [ + .extraSmall: -3, + .small: -2, + .medium: -1, + .large: 0, + .extraLarge: 2, + .extraExtraLarge: 4, + .extraExtraExtraLarge: 6, + .accessibilityMedium: 11, + .accessibilityLarge: 16, + .accessibilityExtraLarge: 23, + .accessibilityExtraExtraLarge: 30, + .accessibilityExtraExtraExtraLarge: 36, + ] + } + + /// The default scaling function. Grows by 2 points for each + /// step above Large, and shrinks by 1 point for each step below Large. + /// This function does not create larger values for content size category + /// values in the Accessibility range of content size categories. + /// + /// - Parameters: + /// - size: The size the font was designed for at `UIContentSizeCategory.large`. + /// - contentSizeCategory: The content size category to scale to. + /// - minimiumSize: The smallest size the font can be. Defaults to 11, or + /// `designatedSize` if `designatedSize` is less than 11. + /// - Returns: The new point size, scaled to the specified content size + public static func adapt(designatedSize size: CGFloat, for contentSizeCategory: BonMotContentSizeCategory, minimiumSize: CGFloat = 11) -> CGFloat { + let shift = min(shiftTable[contentSizeCategory] ?? 0, CGFloat(6)) + let minSize = min(minimiumSize, size) + return max(size + shift, minSize) + } + + /// A scaling function for "body" elements. Continues to grow for content + /// size category values in the Accessibility range. + /// + /// - Parameters: + /// - size: The size the font was designed for at `UIContentSizeCategory.large`. + /// - contentSizeCategory: The content size category to scale to. + /// - minimiumSize: The smallest size the font can be. Defaults to 11. + /// - Returns: The new point size, scaled to the specified contentSize. + public static func adaptBody(designatedSize size: CGFloat, for contentSizeCategory: BonMotContentSizeCategory, minimiumSize: CGFloat = 11) -> CGFloat { + let shift = shiftTable[contentSizeCategory] ?? 0 + let minSize = min(minimiumSize, size) + return max(size + shift, minSize) + } + +} + +extension AdaptiveStyle: EmbeddedTransformation { + + struct Key { + + static let fontName = NSAttributedString.Key("fontName") + + } + + struct Value { + + static let control = "control" + static let body = "body" + static let preferred = "preferred" + static let above = "above" + static let below = "below" + + } + + var asDictionary: StyleAttributes { + switch self { + case let .above(size, family): + return [ + EmbeddedTransformationHelpers.Key.type: Value.above, + EmbeddedTransformationHelpers.Key.size: size, + Key.fontName: family, + ] + case let .below(size, family): + return [ + EmbeddedTransformationHelpers.Key.type: Value.below, + EmbeddedTransformationHelpers.Key.size: size, + Key.fontName: family, + ] + case .control: + return [EmbeddedTransformationHelpers.Key.type: Value.control] + case .body: + return [EmbeddedTransformationHelpers.Key.type: Value.body] + case .preferred: + return [EmbeddedTransformationHelpers.Key.type: Value.preferred] + } + } + + static func from(dictionary dict: StyleAttributes) -> EmbeddedTransformation? { + switch (dict[EmbeddedTransformationHelpers.Key.type] as? String, + dict[EmbeddedTransformationHelpers.Key.size] as? CGFloat, + dict[Key.fontName] as? String) { + case (Value.control?, nil, nil): + return AdaptiveStyle.control + case (Value.body?, nil, nil): + return AdaptiveStyle.body + case (Value.preferred?, nil, nil): + return AdaptiveStyle.preferred + case let (Value.above?, size?, fontName?): + return AdaptiveStyle.above(size: size, useFontNamed: fontName) + case let (Value.below?, size?, fontName?): + return AdaptiveStyle.below(size: size, useFontNamed: fontName) + default: + return nil + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptiveStyleTransformation.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptiveStyleTransformation.swift new file mode 100644 index 0000000..49bb311 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AdaptiveStyleTransformation.swift @@ -0,0 +1,31 @@ +// +// AdaptiveStyleTransformation.swift +// BonMot +// +// Created by Brian King on 9/20/16. +// +// + +import UIKit + +/// Defines a style transformation that is dependent on a `UITraitCollection`. +/// An adaptive transformation is embedded in the `StyleAttributes` so that any +/// `NSAttributedString` can be updated to a new trait collection using +/// `attributedString.adapted(to: traitCollection)`. +/// +/// Since `NSAttributedString` conforms to `NSCoding`, `AdaptiveStyleTransformation` +/// is embedded in the `StyleAttributes` via simple dictionary encoding. +/// `NSCoding` was avoided so that value types can conform. See +/// `EmbeddedTransformation` for more information. +internal protocol AdaptiveStyleTransformation { + + /// Change any of `theAttributes`, as desired, to the specified + /// `traitCollection` and return a new `StyleAttributes` dictionary. + /// + /// - Parameters: + /// - theAttributes: The input attributes. + /// - traitCollection: The trait collection to adapt to. + /// - Returns: The adapted attributes, if any. + func adapt(attributes theAttributes: StyleAttributes, to traitCollection: UITraitCollection) -> StyleAttributes? + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AttributedStringTransformation.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AttributedStringTransformation.swift new file mode 100644 index 0000000..a70eb93 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/AttributedStringTransformation.swift @@ -0,0 +1,23 @@ +// +// AttributedStringTransformation.swift +// BonMot +// +// Created by Brian King on 9/28/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import Foundation + +/// Defines a transformation to be performed on an `NSMutableAttributedString`. +/// It is used for adative transformations that need to know about the content +/// of the string in order to be performed. These are applied after the +/// `AdaptiveStyleTransformation`s are applied. +internal protocol AttributedStringTransformation { + + /// Recalculate any values in the string over the specified range. + /// + /// - parameter string: The attributed string to be updated. + /// - parameter in: The range to operate over. + func update(string theString: NSMutableAttributedString, in range: NSRange) + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/EmbeddedTransformation.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/EmbeddedTransformation.swift new file mode 100644 index 0000000..6fb3eec --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/EmbeddedTransformation.swift @@ -0,0 +1,72 @@ +// +// EmbeddedTransformation.swift +// BonMot +// +// Created by Brian King on 9/28/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +/// BonMot embeds transformation objects inside `NSAttributedString` attributes +/// to do adaptive styling. To simplify `NSAttributedString`'s `NSCoding` +/// support, these transformations get embedded using plist-compatible objects. +/// This protocol defines a contract to simplify this. `NSCoding` is not used so +/// that value types can conform. +internal protocol EmbeddedTransformation { + + /// Return a plist-compatible dictionary of any state that is needed to + /// persist the adaptation + var asDictionary: StyleAttributes { get } + + /// Take the adaptations dictionary and create an array of + /// `AdaptiveStyleTransformation`s. To register a new adaptive transformation, + /// add the type to `EmbeddedTransformationHelpers.embeddedTransformationTypes`. + static func from(dictionary dict: StyleAttributes) -> EmbeddedTransformation? + +} + +// Helpers for managing keys in the `StyleAttributes` related to adaptive functionality. +internal enum EmbeddedTransformationHelpers { + + struct Key { + + static let type = NSAttributedString.Key("type") + static let size = NSAttributedString.Key("size") + + } + + static var embeddedTransformationTypes: [EmbeddedTransformation.Type] = [AdaptiveStyle.self, Tracking.self, Tab.self] + + static func embed(transformation theTransformation: EmbeddedTransformation, to styleAttributes: StyleAttributes) -> StyleAttributes { + let dictionary = theTransformation.asDictionary + var styleAttributes = styleAttributes + var adaptations = styleAttributes[BonMotTransformationsAttributeName] as? [StyleAttributes] ?? [] + + // Only add the transformation once. + let contains = adaptations.contains { NSDictionary(dictionary: $0) == NSDictionary(dictionary: dictionary) } + if !contains { + adaptations.append(dictionary) + } + styleAttributes[BonMotTransformationsAttributeName] = adaptations + return styleAttributes + } + + static func transformations(from styleAttributes: StyleAttributes) -> [T] { + let representations = styleAttributes[BonMotTransformationsAttributeName] as? [StyleAttributes] ?? [] + let results: [T?] = representations.map { representation in + for type in embeddedTransformationTypes { + if let transformation = type.from(dictionary: representation) as? T { + return transformation + } + } + return nil + } + return results.compactMap({ $0 }) + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/NSAttributedString+Adaptive.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/NSAttributedString+Adaptive.swift new file mode 100644 index 0000000..e4f6c13 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/NSAttributedString+Adaptive.swift @@ -0,0 +1,79 @@ +// +// NSAttributedString+Adapt.swift +// BonMot +// +// Created by Brian King on 9/20/16. +// +// + +import UIKit + +extension NSAttributedString { + + /// Adapt a set of attributes to the specified trait collection. This will + /// use the style object defined in the attributes or use the default style + /// object specified. + /// + /// - Parameters: + /// - theAttributes: The attributes to transform. + /// - traitCollection: The trait collection to which to adapt the attributes. + /// - Returns: Attributes with fonts updated to the specified contect size category. + public static func adapt(attributes theAttributes: StyleAttributes, to traitCollection: UITraitCollection) -> StyleAttributes { + let adaptations: [AdaptiveStyleTransformation] = EmbeddedTransformationHelpers.transformations(from: theAttributes) + var styleAttributes = theAttributes + for adaptiveStyle in adaptations { + styleAttributes = adaptiveStyle.adapt(attributes: styleAttributes, to: traitCollection) ?? styleAttributes + } + return styleAttributes + } + + /// Create a new `NSAttributedString` adapted to the new trait collection. + /// Re-applies the embedded style objects. + /// + /// - Parameter traitCollection: The trait collection to adapt to. + /// - Returns: A new `NSAttributedString` with the style updated to the new + /// trait collection. + public final func adapted(to traitCollection: UITraitCollection) -> NSAttributedString { + let newString = mutableStringCopy() + newString.beginEditing() + enumerateAttributes(in: NSRange(location: 0, length: length), options: []) { (attributes, range, _) in + var styleAttributes = attributes + + // Adapt any AdaptiveStyleTransformation embedded in the attributes. + let adaptiveStyles: [AdaptiveStyleTransformation] = EmbeddedTransformationHelpers.transformations(from: attributes) + for adaptiveStyle in adaptiveStyles { + styleAttributes = adaptiveStyle.adapt(attributes: styleAttributes, to: traitCollection) ?? styleAttributes + } + // Apply any AttributedStringTransformation embedded in the attributes. + let transformations: [AttributedStringTransformation] = EmbeddedTransformationHelpers.transformations(from: attributes) + for transformation in transformations { + transformation.update(string: newString, in: range) + } + newString.setAttributes(NSAttributedString.adapt(attributes: attributes, to: traitCollection), range: range) + } + newString.endEditing() + return newString + } + +} + +extension StringStyle { + + /// Adapt the receiver's attributes to the provided trait collection. + /// + /// - Parameter traitCollection: The trait collection to adapt to. + /// - Returns: The adapted attributes. + public func attributes(adaptedTo traitCollection: UITraitCollection) -> StyleAttributes { + return NSAttributedString.adapt(attributes: attributes, to: traitCollection) + } + +} + +// MARK: - Deprecations +extension NSAttributedString { + + @available(*, deprecated, renamed: "adapted(to:)") public final func adapt(to traitCollection: UITraitCollection) -> NSAttributedString { + return adapted(to: traitCollection) + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/StyleableUIElement.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/StyleableUIElement.swift new file mode 100644 index 0000000..bcef35d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/StyleableUIElement.swift @@ -0,0 +1,263 @@ +// +// StyleableUIElement.swift +// BonMot +// +// Created by Brian King on 8/11/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import UIKit + +extension UILabel { + + /// The name of a style in the global `NamedStyles` registry. The getter + /// always returns `nil`, and should not be used. + @IBInspectable + public var bonMotStyleName: String? { + get { return nil } + set { bonMotStyle = StyleableUIElementHelpers.lookUpSharedStyle(for: newValue, font: font) } + } + + /// A string style. Stored via associated objects. + public final var bonMotStyle: StringStyle? { + get { return StyleableUIElementHelpers.getAssociatedStyle(from: self) } + set { + StyleableUIElementHelpers.setAssociatedStyle(on: self, style: newValue) + styledText = text + } + } + + /// Update this property to style the incoming text via the `bonMotStyle` + /// and set it as the receiver's `attributedText`. + @objc(bon_styledText) + public var styledText: String? { + get { return attributedText?.string } + set { attributedText = StyleableUIElementHelpers.styledAttributedString(from: newValue, style: bonMotStyle, traitCollection: traitCollection) } + } + +} + +extension UITextField { + + /// The name of a style in the global `NamedStyles` registry. The getter + /// always returns `nil`, and should not be used. + /// + /// - note: The style is applied to both the `attributedText` and + /// `defaultTextAttributes`. If you plan on styling them differently, use + /// attributed strings directly. + @IBInspectable + public var bonMotStyleName: String? { + get { return nil } + set { + guard let font = font else { fatalError("Unable to get the font. This is unexpected, see UIKitTests.testTextFieldPropertyBehavior") } + bonMotStyle = StyleableUIElementHelpers.lookUpSharedStyle(for: newValue, font: font) + } + } + + /// A string style. Stored via associated objects. + /// - note: The style is applied to both the `attributedText` and + /// `attributedPlaceholder`. If you plan on styling them differently, use + /// attributed strings directly. + public final var bonMotStyle: StringStyle? { + get { return StyleableUIElementHelpers.getAssociatedStyle(from: self) } + set { + StyleableUIElementHelpers.setAssociatedStyle(on: self, style: newValue) + styledText = text + let attributes = (bonMotStyle?.attributes(adaptedTo: traitCollection) ?? [:]) + #if swift(>=4.2) + defaultTextAttributes = attributes + #else + defaultTextAttributes = attributes.withStringKeys + #endif + } + } + + /// Update this property to style the incoming text via the `bonMotStyle` + /// and set it as the receiver's `attributedText`. + @objc(bon_styledText) + public var styledText: String? { + get { return attributedText?.string } + set { + let styledText = StyleableUIElementHelpers.styledAttributedString(from: newValue, style: bonMotStyle, traitCollection: traitCollection) + // Set the font first to avoid a bug that causes UITextField to hang + if let styledText = styledText { + if styledText.length > 0 { + font = styledText.attribute(.font, at: 0, effectiveRange: nil) as? UIFont + } + } + attributedText = styledText + } + } + +} + +extension UITextView { + + /// The name of a style in the global `NamedStyles` registry. The getter + /// always returns `nil`, and should not be used. + /// + /// - note: The style is applied to both the `attributedText` and + /// `typingAttributes`. If you plan on styling them differently, use + /// attributed strings directly. + @IBInspectable + public var bonMotStyleName: String? { + get { return nil } + set { + let font: UIFont + if let configuredFont = self.font { + font = configuredFont + } + else { + // If the text property is not and has not been set, the font property is nil. Use the platform specific default values here + // See UIKitTests.testTextFieldPropertyBehavior + #if os(iOS) + font = UIFont.systemFont(ofSize: 12) + #elseif os(tvOS) + font = UIFont.systemFont(ofSize: 38) + #else + fatalError("Unsupported Mystery Platform") + #endif + } + bonMotStyle = StyleableUIElementHelpers.lookUpSharedStyle(for: newValue, font: font) + } + } + + /// A string style. Stored via associated objects. + /// - note: The style is applied to both the `attributedText` and + /// `typingAtributes`. If you plan on styling them differently, use + /// attributed strings directly. + public final var bonMotStyle: StringStyle? { + get { return StyleableUIElementHelpers.getAssociatedStyle(from: self) } + set { + StyleableUIElementHelpers.setAssociatedStyle(on: self, style: newValue) + #if swift(>=4.2) + typingAttributes = newValue?.attributes(adaptedTo: traitCollection) ?? typingAttributes + #else + typingAttributes = newValue?.attributes(adaptedTo: traitCollection).withStringKeys ?? typingAttributes + #endif + styledText = text + } + } + + /// Update this property to style the incoming text via the `bonMotStyle` + /// and set it as the receiver's `attributedText`. + @objc(bon_styledText) + public var styledText: String? { + get { return attributedText?.string } + set { + attributedText = StyleableUIElementHelpers.styledAttributedString(from: newValue, style: bonMotStyle, traitCollection: traitCollection) + } + } + +} + +extension UIButton { + + /// The name of a style in the global `NamedStyles` registry. The getter + /// always returns `nil`, and should not be used. + @IBInspectable + public var bonMotStyleName: String? { + get { return nil } + set { + guard let font = titleLabel?.font else { fatalError("Unable to get the font. This is unexpected; see UIKitTests.testTextFieldPropertyBehavior") } + bonMotStyle = StyleableUIElementHelpers.lookUpSharedStyle(for: newValue, font: font) + } + } + + /// A string style. Stored via associated objects. + public final var bonMotStyle: StringStyle? { + get { return StyleableUIElementHelpers.getAssociatedStyle(from: self) } + set { + StyleableUIElementHelpers.setAssociatedStyle(on: self, style: newValue) + styledText = titleLabel?.text + } + } + + /// Update this property to style the incoming text via the `bonMotStyle` + /// and set it as the receiver's attributed text for the "normal" state. + @objc(bon_styledText) + public var styledText: String? { + get { return titleLabel?.text } + set { + let styledText = StyleableUIElementHelpers.styledAttributedString(from: newValue, style: bonMotStyle, traitCollection: traitCollection) + setAttributedTitle(styledText, for: .normal) + } + } + +} + +/// Helper for the bonMotStyle associated objects. +private var containerHandle: UInt8 = 0 +private enum StyleableUIElementHelpers { + + static func getAssociatedStyle(from object: AnyObject) -> StringStyle? { + let adaptiveFunctionContainer = objc_getAssociatedObject(object, &containerHandle) as? StringStyleHolder + return adaptiveFunctionContainer?.style + } + + static func setAssociatedStyle(on object: AnyObject, style: StringStyle?) { + var adaptiveFunction: StringStyleHolder? + if let bonMotStyle = style { + adaptiveFunction = StringStyleHolder(style: bonMotStyle) + } + objc_setAssociatedObject( + object, &containerHandle, + adaptiveFunction, + .OBJC_ASSOCIATION_RETAIN_NONATOMIC + ) + } + + static func styledAttributedString(from string: String?, style: StringStyle?, traitCollection: UITraitCollection) -> NSAttributedString? { + guard let string = string else { return nil } + let attributedString = (style ?? StringStyle()).attributedString(from: string) + return attributedString.adapted(to: traitCollection) + } + + static func lookUpSharedStyle(for name: String?, font: UIFont) -> StringStyle? { + guard let name = name, let style = NamedStyles.shared.style(forName: name) else { + return nil + } + // Create a style with the font and then add the named style. + // This will provide a font if one is not specified in the style. + return StringStyle(.font(font)).byAdding(stringStyle: style) + } + +} + +@objc(BONStringStyleHolder) +internal class StringStyleHolder: NSObject { + + let style: StringStyle + init(style: StringStyle) { + self.style = style + } + +} + +extension Dictionary where Key: RawRepresentable, Key.RawValue == String { + + var withStringKeys: [String: Value] { + var newDict: [String: Value] = [:] + for (key, value) in self { + newDict[key.rawValue] = value + } + + return newDict + } + +} + +extension Dictionary where Key == String { + + func withTypedKeys() -> [KeyType: Value] where KeyType: RawRepresentable, KeyType.RawValue == String { + var newDict: [KeyType: Value] = [:] + for (key, value) in self { + if let newKey = KeyType(rawValue: key) { + newDict[newKey] = value + } + } + + return newDict + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/Tab+Adaptive.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/Tab+Adaptive.swift new file mode 100644 index 0000000..f72ff96 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/Tab+Adaptive.swift @@ -0,0 +1,56 @@ +// +// Tab+Adaptive.swift +// BonMot +// +// Created by Brian King on 10/2/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +// Just declare conformance. Implementation is already defined and used even +// if adaptive code is not included in the target. +extension Tab: AttributedStringTransformation { } + +extension Tab: EmbeddedTransformation { + + struct Value { + + static let spacer = "spacer" + static let headIndent = "headIndent" + + } + + static func from(dictionary dict: StyleAttributes) -> EmbeddedTransformation? { + switch (dict[EmbeddedTransformationHelpers.Key.type] as? String, + dict[EmbeddedTransformationHelpers.Key.size] as? CGFloat) { + case (Value.spacer?, let width?): + return Tab.spacer(width) + case (Value.headIndent?, let width?): + return Tab.headIndent(width) + default: + return nil + } + } + + var asDictionary: StyleAttributes { + switch self { + case let .spacer(size): + return [ + EmbeddedTransformationHelpers.Key.type: Value.spacer, + EmbeddedTransformationHelpers.Key.size: size, + ] + + case let .headIndent(size): + return [ + EmbeddedTransformationHelpers.Key.type: Value.headIndent, + EmbeddedTransformationHelpers.Key.size: size, + ] + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/TextAlignmentConstraint.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/TextAlignmentConstraint.swift new file mode 100644 index 0000000..bdb8dc1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/TextAlignmentConstraint.swift @@ -0,0 +1,240 @@ +// +// TextAlignmentConstraint.swift +// BonMot +// +// Created by Cameron Pulsford on 10/4/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +private var TextAlignmentConstraintKVOContext = "BonMotTextAlignmentConstraintKVOContext" as NSString + +/// Used to align various UI controls (anything with a font or attribute text) +/// by properties that are not available with stock constraints: +/// - cap height (the tops of capital letters) +/// - x-height (the height of a lowercase "x") +@objc(BONTextAlignmentConstraint) +public class TextAlignmentConstraint: NSLayoutConstraint { + + @objc(BONTextAlignmentConstraintAttribute) + public enum TextAttribute: Int, CustomStringConvertible { + + case unspecified + case top + case capHeight + case xHeight + case firstBaseline + case lastBaseline + case bottom + + var layoutAttribute: NSLayoutConstraint.Attribute { + switch self { + case .top, .capHeight, .firstBaseline, .xHeight: + return .top + case .lastBaseline, .bottom: + return .bottom + case .unspecified: + return .notAnAttribute + } + } + + static private let ibInspectableMapping: [String: TextAttribute] = [ + "unspecified": .unspecified, + "top": .top, + "capheight": .capHeight, + "xheight": .xHeight, + "firstbaseline": .firstBaseline, + "lastbaseline": .lastBaseline, + "bottom": .bottom, + ] + + public var description: String { + switch self { + case .unspecified: + return "unspecified" + case .top: + return "top" + case .capHeight: + return "cap height" + case .xHeight: + return "x-height" + case .firstBaseline: + return "first baseline" + case .lastBaseline: + return "last baseline" + case .bottom: + return "bottom" + } + } + + init(ibInspectableString string: String) { + self = TextAttribute.ibInspectableMapping[string] ?? .unspecified + } + + } + + @IBInspectable public var firstAlignment: String? { + didSet { + firstItemAttribute = TextAttribute(ibInspectableString: firstAlignment?.normalized ?? "") + } + } + + @IBInspectable public var secondAlignment: String? { + didSet { + secondItemAttribute = TextAttribute(ibInspectableString: secondAlignment?.normalized ?? "") + } + } + + public private(set) var firstItemAttribute: TextAttribute = .unspecified + public private(set) var secondItemAttribute: TextAttribute = .unspecified + private var item1: AnyObject! + private var item2: AnyObject! + + // The class part of these selectors are ignored; it is there simply to satisfy Xcode's selector syntax. + private static let fontSelector = #selector(getter: BONTextField.font) + + #if os(OSX) + private static let attributedTextSelector = #selector(getter: NSTextField.attributedStringValue) + #else + private static let attributedTextSelector = #selector(getter: UITextField.attributedText) + #endif + + /// Construct a new `TextAlignmentConstraint`. + /// + /// - Parameters: + /// - view1: The view for the left side of the constraint equation. + /// - attr1: The attribute of the view for the left side of the constraint equation. + /// - relation: The relationship between the left and right side of the constraint equation. + /// - view2: The view for the right side of the constraint equation. + /// - attr2: The attribute of the view for the right side of the constraint equation. + /// - Returns: A constraint object relating the two provided views with the + /// specified relation and attributes. + public static func with( + item view1: AnyObject, attribute attr1: TextAttribute, relatedBy relation: NSLayoutConstraint.Relation, toItem view2: AnyObject, attribute attr2: TextAttribute) -> TextAlignmentConstraint { + let constraint = TextAlignmentConstraint( + item: view1, + attribute: attr1.layoutAttribute, + relatedBy: relation, + toItem: view2, + attribute: attr2.layoutAttribute, + multiplier: 1, + constant: 0) + + constraint.item1 = view1 + constraint.item2 = view2 + constraint.firstItemAttribute = attr1 + constraint.secondItemAttribute = attr2 + + constraint.setupObservers() + constraint.updateConstant() + + return constraint + } + + deinit { + tearDownObservers() + } + + public override func awakeFromNib() { + super.awakeFromNib() + setupObservers() + updateConstant() + } + + private func setupObservers() { + for keyPath in fontKeyPaths { + addObserver(self, forKeyPath: keyPath, options: [], context: &TextAlignmentConstraintKVOContext) + } + } + + private func tearDownObservers() { + for keyPath in fontKeyPaths { + removeObserver(self, forKeyPath: keyPath, context: &TextAlignmentConstraintKVOContext) + } + } + + private var fontKeyPaths: [String] { + let firstItemSelector = #selector(getter: NSLayoutConstraint.firstItem) + let secondItemSelector = #selector(getter: NSLayoutConstraint.secondItem) + + return [ + "\(firstItemSelector).\(TextAlignmentConstraint.fontSelector)", + "\(firstItemSelector).\(TextAlignmentConstraint.attributedTextSelector)", + "\(secondItemSelector).\(TextAlignmentConstraint.fontSelector)", + "\(secondItemSelector).\(TextAlignmentConstraint.attributedTextSelector)", + ] + } + + // Can't use block-based KVO until we can use \NSLayoutConstraint.firstItem + //swiftlint:disable:next block_based_kvo + public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { + guard context == &TextAlignmentConstraintKVOContext else { + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + return + } + + updateConstant() + } + + private func updateConstant() { + #if os(OSX) + let distanceFromTop1 = distanceFromTop(of: firstItem!, with: firstItemAttribute) + #else + let distanceFromTop1 = distanceFromTop(of: firstItem!, with: firstItemAttribute) + #endif + + let distanceFromTop2 = distanceFromTop(of: secondItem!, with: secondItemAttribute) + let difference = distanceFromTop2 - distanceFromTop1 + constant = difference + } + + private func distanceFromTop(of item: AnyObject, with attribute: TextAttribute) -> CGFloat { + guard let font = font(from: item) else { + return 0 + } + + let topToBaseline = font.ascender + let distanceFromTop: CGFloat + + switch attribute { + case .capHeight: + distanceFromTop = topToBaseline - font.capHeight + case .xHeight: + distanceFromTop = topToBaseline - font.xHeight + case .top: + distanceFromTop = 0 + case .firstBaseline, .lastBaseline, .bottom: + fatalError("\(attribute) alignment is not currently supported with \(self). Please check https://github.com/Raizlabs/BonMot/issues/37 for progress on this issue.") + case .unspecified: + fatalError("Attempt to reason about unspecified constraint attribute") + } + + return distanceFromTop + } + + private func font(from item: AnyObject) -> BONFont? { + var font: BONFont? + + if item.responds(to: TextAlignmentConstraint.fontSelector) { + font = item.perform(TextAlignmentConstraint.fontSelector).takeUnretainedValue() as? BONFont + } + + return font + } +} + +private extension String { + + var normalized: String { + var n = self.lowercased() + n = n.components(separatedBy: CharacterSet.letters.inverted).joined(separator: "") + n = n.components(separatedBy: CharacterSet.whitespacesAndNewlines).joined(separator: "") + return n + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/Tracking+Adaptive.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/Tracking+Adaptive.swift new file mode 100644 index 0000000..42bd515 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/Tracking+Adaptive.swift @@ -0,0 +1,58 @@ +// +// Tracking+Adaptive.swift +// BonMot +// +// Created by Brian King on 10/2/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +extension Tracking: AdaptiveStyleTransformation { + + func adapt(attributes theAttributes: StyleAttributes, to traitCollection: UITraitCollection) -> StyleAttributes? { + if case .adobe = self { + var attributes = theAttributes + let styledFont = theAttributes[.font] as? UIFont + attributes.update(possibleValue: kerning(for: styledFont), forKey: .kern) + return attributes + } + else { + return nil + } + } + +} + +extension Tracking: EmbeddedTransformation { + + struct Value { + static let adobeTracking = "adobe-tracking" + } + + static func from(dictionary dict: StyleAttributes) -> EmbeddedTransformation? { + if case let (Value.adobeTracking?, size?) = (dict[EmbeddedTransformationHelpers.Key.type] as? String, dict[EmbeddedTransformationHelpers.Key.size] as? CGFloat) { + return Tracking.adobe(size) + } + return nil + } + + var asDictionary: StyleAttributes { + if case let .adobe(size) = self { + return [ + EmbeddedTransformationHelpers.Key.type: Value.adobeTracking, + EmbeddedTransformationHelpers.Key.size: size, + ] + } + else { + // We don't need to persist point tracking, as it does not depend on + // the font size. + return [:] + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift new file mode 100644 index 0000000..d09d205 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift @@ -0,0 +1,83 @@ +// +// UIKit+AdaptableTextContainerSupport.swift +// BonMot +// +// Created by Brian King on 7/19/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +import UIKit + +extension UIApplication { + + /// Support for the `AdaptableTextContainer` protocol is enabled with this + /// method. It adds the application as an observer for `UIContentSizeCategoryDidChangeNotification` + /// and floods the change notification to the `UIViewController` hierarchy, + /// which by default floods the view managed by each `UIViewController`. + /// + /// The `UIApplication` delegate is also checked for conformance to + /// `AdaptableTextContainer`, which can be a good place to update appearance + /// proxies and invalidate any hard-wired caches that less responsive code may have. + public final func enableAdaptiveContentSizeMonitor() { + let notificationCenter = NotificationCenter.default + let notificationName = UIContentSizeCategory.didChangeNotification + notificationCenter.addObserver( + self, + selector: #selector(UIApplication.bon_notifyContainedAdaptiveContentSizeContainers(fromNotification:)), + name: notificationName, + object: nil) + } + + // Notify the view controller hierarchy. + @objc internal func bon_notifyContainedAdaptiveContentSizeContainers(fromNotification notification: NSNotification) { + // First notify the app delegate if it conforms to AdaptableTextContainer. + if let container = delegate, let traitCollection = container.window??.traitCollection { + if container.responds(to: #selector(AdaptableTextContainer.adaptText(forTraitCollection:))) { + container.perform(#selector(AdaptableTextContainer.adaptText(forTraitCollection:)), with: traitCollection) + } + } + + for window in windows { + // Notify all views in the view hierarchy + window.notifyContainedAdaptiveContentSizeContainers() + // Notify all of the view controllers + window.rootViewController?.notifyContainedAdaptiveContentSizeContainers() + } + } + +} + +extension UIViewController { + + /// 1. If the view is loaded and not installed in the view hierarchy, notify + /// the receiver's view and subviews. If the view is in the view hierarchy, + /// it has already been notified, so do not notify again. + /// 2. Then notify all child view controllers, then the presented view controller, if any. + final func notifyContainedAdaptiveContentSizeContainers() { + if let view = viewIfLoaded { + if view.window == nil { + view.notifyContainedAdaptiveContentSizeContainers() + } + } + for viewController in children { + viewController.notifyContainedAdaptiveContentSizeContainers() + } + presentedViewController?.notifyContainedAdaptiveContentSizeContainers() + adaptText(forTraitCollection: traitCollection) + } + +} + +extension UIView { + + /// Notify any subviews, then notify the receiver if it conforms to `AdaptableTextContainer`. + final func notifyContainedAdaptiveContentSizeContainers() { + for view in subviews { + view.notifyContainedAdaptiveContentSizeContainers() + } + if responds(to: #selector(AdaptableTextContainer.adaptText(forTraitCollection:))) { + perform(#selector(AdaptableTextContainer.adaptText(forTraitCollection:)), with: traitCollection) + } + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/UIKit+Helpers.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/UIKit+Helpers.swift new file mode 100644 index 0000000..2694413 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/UIKit/UIKit+Helpers.swift @@ -0,0 +1,75 @@ +// +// UIKit+Helpers.swift +// BonMot +// +// Created by Brian King on 9/12/16. +// +// + +import UIKit + +// UIKit helpers for iOS and tvOS + +extension UIFont { + + @nonobjc static func bon_preferredFont(forTextStyle textStyle: BonMotTextStyle, compatibleWith traitCollection: UITraitCollection?) -> UIFont { + if #available(iOS 10.0, tvOS 10.0, *) { + return preferredFont(forTextStyle: textStyle, compatibleWith: traitCollection) + } + else { + return preferredFont(forTextStyle: textStyle) + } + } + + /// Retrieve the text style, if it exists, from the font descriptor. + @objc(bon_textStyle) + public final var textStyle: BonMotTextStyle? { + guard let textStyle = fontDescriptor.fontAttributes[UIFontDescriptor.AttributeName.textStyle] as? String else { + return nil + } + return UIFont.TextStyle(rawValue: textStyle) + } + +} + +extension UITraitCollection { + + /// Obtain the `preferredContentSizeCategory` for the trait collection. This + /// is compatible with iOS 9.x and will use the + /// `UIApplication.shared.preferredContentSizeCategory` if the trait collection's + /// `preferredContentSizeCategory` is `UIContentSizeCategory.unspecified`. + public var bon_preferredContentSizeCategory: BonMotContentSizeCategory { + if #available(iOS 10.0, tvOS 10.0, *) { + if preferredContentSizeCategory != .unspecified { + return preferredContentSizeCategory + } + } + // `UIApplication.shared` is not a valid object in unit tests. Fall back + // to a default value if the delegate is nil. + if UIApplication.shared.delegate != nil { + return UIApplication.shared.preferredContentSizeCategory + } + else { + return UIContentSizeCategory.large + } + } + +} + +extension UIFont { + + /// Uses a font descriptor to return a font with the specified name, but + /// with all other attributes the same as the receiver. + /// + /// - Parameter name: The name of the new font. Use the same name as you + /// would pass to UIFont(name:size:). + /// - Returns: a font with the same attributes as the receiver, but with the + /// the specified name. + final func fontWithSameAttributes(named name: String) -> UIFont { + let descriptor = fontDescriptor.addingAttributes([ + UIFontDescriptor.AttributeName.name: name, + ]) + return UIFont(descriptor: descriptor, size: pointSize) + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/XMLBuilder.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/XMLBuilder.swift new file mode 100644 index 0000000..de091ba --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/BonMot/Sources/XMLBuilder.swift @@ -0,0 +1,347 @@ +// +// NamedStyles+XML.swift +// BonMot +// +// Created by Brian King on 8/29/16. +// Copyright © 2016 Raizlabs. All rights reserved. +// + +#if os(OSX) + import AppKit +#else + import UIKit +#endif + +extension NSAttributedString { + + /// Generate an attributed string by parsing `fragment` using the `XMLStyler` + /// protocol to provide style and string insertions to decorate the XML. As + /// the XML fragment is traversed, the style of each node is provided by the + /// `XMLStyler` protocol. This style and the current style are combined to + /// decorate the content of the node, and the added style is removed when + /// the node is exited. The `XMLStyler` protocol can also insert + /// `NSAttributedString`s when entering and exiting nodes to support more + /// customized styling. + /// + /// The `fragment` string will be wrapped in a top level element to ensure + /// that it is valid XML, unless `XMLParsingOptions.doNotWrapXML` is + /// specified as an option. If the XML is not valid, an error will be thrown. + /// + /// - Parameters: + /// - fragment: The string containing the markup. + /// - baseStyle: The base style to use where the XML does not otherwise + /// specify styling options. + /// - styler: An optional custom styler to perform extra style operations. + /// - options: XML parsing options. + /// - Returns: A styled attriubted string. + /// - Throws: Any errors encountered by the XML parser. + public static func composed(ofXML fragment: String, baseStyle: StringStyle? = nil, styler: XMLStyler? = nil, options: XMLParsingOptions = []) throws -> NSAttributedString { + let builder = XMLBuilder( + string: fragment, + styler: styler ?? NSAttributedString.defaultXMLStyler, + options: options, + baseStyle: baseStyle ?? StringStyle() + ) + let attributedString = try builder.parseAttributedString() + return attributedString + } + + /// Generate an attributed string by parsing `fragment` using the collection + /// of `XMLStyleRule`s to provide style and string insertions to decorate + /// the XML. As the XML fragment is traversed, the style of each node is + /// provided by the `StyleRule`s. This style and the current style are + /// combined to decorate the content of the node, and the added style is + /// removed when the node is exited. The `XMLStyleRule` can also insert + /// `NSAttributedString`s when entering and exiting nodes to support more + /// customized styling. + /// + /// For more complex styling behavior, implement the `XMLStyler` protocol + /// instead. + /// + /// The `fragment` string will be wrapped in a top level element to ensure + /// that it is valid XML, unless `XMLParsingOptions.doNotWrapXML` is + /// specified as an option. If the XML is not valid, an error will be thrown. + /// + /// - Parameters: + /// - fragment: The string containing the markup. + /// - baseStyle: The base style to use where the XML does not otherwise + /// specify styling options. + /// - rules: Styling rules to evaluate while parsing the XML. + /// - options: XML parsing options. + /// - Returns: A styled attriubted string. + /// - Throws: Any errors encountered by the XML parser. + public static func composed(ofXML fragment: String, baseStyle: StringStyle? = nil, rules: [XMLStyleRule], options: XMLParsingOptions = []) throws -> NSAttributedString { + let builder = XMLBuilder( + string: fragment, + styler: XMLStyleRule.Styler(rules: rules), + options: options, + baseStyle: baseStyle ?? StringStyle() + ) + let attributedString = try builder.parseAttributedString() + return attributedString + } + + /// The default `XMLStyler` to use. By default, this styler will look up + /// element styles in the shared `NamedStyles` and insert special characters + /// when BON-namespaced elements are encountered. + @nonobjc public static var defaultXMLStyler: XMLStyler = { + var rules = Special.insertionRules + rules.append(.styles(NamedStyles.shared)) + return XMLStyleRule.Styler(rules: rules) + }() + +} + +extension Special { + + /// Rules describing how to insert values from `Special` into attributed strings. + public static var insertionRules: [XMLStyleRule] { + let rulePairs: [[XMLStyleRule]] = all.map { + let elementName = "BON:\($0.name)" + // Add the insertion rule and a style rule so we don't look up the style and generate a warning + return [XMLStyleRule.enter(element: elementName, insert: $0), XMLStyleRule.style(elementName, StringStyle())] + } + return rulePairs.flatMap { $0 } + } + +} + +/// A simple set of styling rules for styling XML. If your needs are more +/// complicated, use the `XMLStyler` protocol. +public enum XMLStyleRule { + + /// A collection of named styles. + case styles(NamedStyles) + + /// A name/style pairing. + case style(String, StringStyle) + + /// A `Composable` to insert before entering tags whose name equals `element`. + case enter(element: String, insert: Composable) + + /// A `Composable` to insert before exiting tags whose name equals `element`. + case exit(element: String, insert: Composable) + + /// An `XMLStyler` implementation for handling `XMLStyleRule`s. + struct Styler: XMLStyler { + + let rules: [XMLStyleRule] + + func style(forElement name: String, attributes: [String: String], currentStyle: StringStyle) -> StringStyle? { + for rule in rules { + switch rule { + case let .style(string, style) where string == name: + return style + default: + break + } + } + for rule in rules { + if case let .styles(namedStyles) = rule { + return namedStyles.style(forName: name) + } + } + return nil + } + + func prefix(forElement name: String, attributes: [String: String]) -> Composable? { + for rule in rules { + switch rule { + case let .enter(string, composable) where string == name: + return composable + default: break + } + } + return nil + } + + func suffix(forElement name: String) -> Composable? { + for rule in rules { + switch rule { + case let .exit(string, composable) where string == name: + return composable + default: break + } + } + return nil + } + + } + +} + +/// A contract to transform an XML string into an attributed string. +public protocol XMLStyler { + + /// Return the style to apply for to the contents of the element. The style + /// is added onto the current style + func style(forElement name: String, attributes: [String: String], currentStyle: StringStyle) -> StringStyle? + + /// Provide a `Composable` to add into the string being built before the + /// named element. This is done after the style for the element has been + /// applied, but before the contents of the element. + func prefix(forElement name: String, attributes: [String: String]) -> Composable? + + /// Provide a `Composable` to add into the string being built when leaving + /// the element. This is done before the style of the element is removed. + func suffix(forElement name: String) -> Composable? + +} + +/// Options to control the behavior of the XML parser. +public struct XMLParsingOptions: OptionSet { + + public let rawValue: Int + + // Must be explicitly declared because it has to be marked public. + public init(rawValue: Int) { self.rawValue = rawValue } + + /// Do not wrap the fragment with a top-level element. Wrapping the XML will + /// cause a copy of the entire XML string, so for very large strings, it is + /// recommended that you include a root node yourself and pass this option. + public static let doNotWrapXML = XMLParsingOptions(rawValue: 1) + +} + +/// Error wrapper that includes the line and column number of the error. +public struct XMLBuilderError: Error { + + /// The error generated by XMLParser. + public let parserError: Error + + /// The line number where the error occurred. + public let line: Int + + /// The column where the error occurred. + public let column: Int + +} + +class XMLBuilder: NSObject, XMLParserDelegate { + + static let internalTopLevelElement = "BonMotTopLevelContainer" + + let parser: XMLParser + let options: XMLParsingOptions + var attributedString: NSMutableAttributedString + var styles: [StringStyle] + var xmlStylers: [XMLStyler] + + // The XML parser sometimes splits strings, which can break localization-sensitive + // string transforms. Work around this by using the currentString variable to + // accumulate partial strings, and then reading them back out as a single string + // when the current element ends, or when a new one is started. + var currentString: String? + + var topStyle: StringStyle { + guard let style = styles.last else { fatalError("Invalid Style Stack") } + return style + } + + var topXMLStyler: XMLStyler { + guard let styler = xmlStylers.last else { fatalError("Invalid Style Stack") } + return styler + } + + init(string: String, + styler: XMLStyler, + options: XMLParsingOptions, + baseStyle: StringStyle) { + let xml = (options.contains(.doNotWrapXML) ? + string : + "<\(XMLBuilder.internalTopLevelElement)>\(string)") + + guard let data = xml.data(using: String.Encoding.utf8) else { + fatalError("Unable to convert to UTF8") + } + self.attributedString = NSMutableAttributedString() + self.parser = XMLParser(data: data) + self.options = options + self.xmlStylers = [styler] + // Remove the XMLStyler from the base style + var style = baseStyle + style.xmlStyler = nil + self.styles = [style] + super.init() + self.parser.shouldProcessNamespaces = false + self.parser.shouldReportNamespacePrefixes = false + self.parser.shouldResolveExternalEntities = false + self.parser.delegate = self + } + + func parseAttributedString() throws -> NSMutableAttributedString { + guard parser.parse() else { + let line = parser.lineNumber + let shiftColumn = (line == 1 && options.contains(.doNotWrapXML) == false) + let shiftSize = XMLBuilder.internalTopLevelElement.lengthOfBytes(using: String.Encoding.utf8) + 2 + let column = parser.columnNumber - (shiftColumn ? shiftSize : 0) + + throw XMLBuilderError(parserError: parser.parserError!, line: line, column: column) + } + return attributedString + } + + /// When a node is entered, a new style is derived from the current style + /// and the style for the node returned by the XMLStyler. If the style + /// contains an `XMLStyler`, it is pushed onto the `XMLStyler` stack and + /// + /// - Parameters: + /// - elementName: The name of the XML element. + /// - attributes: The XML attributes. + func enter(element elementName: String, attributes: [String: String]) { + guard elementName != XMLBuilder.internalTopLevelElement else { return } + + let xmlStyler = topXMLStyler + let namedStyle = xmlStyler.style(forElement: elementName, attributes: attributes, currentStyle: topStyle) + var newStyle = topStyle + if let namedStyle = namedStyle { + newStyle.add(stringStyle: namedStyle) + } + + // Update the style stack. The XML styler is removed from the style and + // added to its own stack to prevent the XML parsing from being + // re-entrant and occuring on every character group. + xmlStylers.append(newStyle.xmlStyler ?? topXMLStyler) + newStyle.xmlStyler = nil + styles.append(newStyle) + + // The prefix is looked up in the styler that styled this node, not the new styler + if let prefix = xmlStyler.prefix(forElement: elementName, attributes: attributes) { + prefix.append(to: attributedString, baseStyle: newStyle) + } + + } + + func exit(element elementName: String) { + if let suffix = topXMLStyler.suffix(forElement: elementName) { + suffix.append(to: attributedString, baseStyle: topStyle) + } + styles.removeLast() + xmlStylers.removeLast() + } + + func foundNewString() { + guard let newString = currentString else { + return + } + let newAttributedString = topStyle.attributedString(from: newString) + attributedString.append(newAttributedString) + currentString = nil + } + + @objc func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String]) { + foundNewString() + enter(element: elementName, attributes: attributeDict) + } + + @objc func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { + foundNewString() + guard elementName != XMLBuilder.internalTopLevelElement else { return } + exit(element: elementName) + } + + @objc func parser(_ parser: XMLParser, foundCharacters string: String) { + currentString = (currentString ?? "").appending(string) + } + +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/Crashlytics.framework/README b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/Crashlytics.framework/README new file mode 100644 index 0000000..3ebf767 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/Crashlytics.framework/README @@ -0,0 +1 @@ +We've now combined all our supported platforms into a single podspec. As a result, we moved our submit script to a new location for Cocoapods projects: ${PODS_ROOT}/Crashlytics/submit. To avoid breaking functionality that references the old location of the submit, we've placed this dummy script that calls to the correct location, while providing a helpful warning if it is invoked. This bridge for backwards compatibility will be removed in a future release, so please heed the warning! diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/Crashlytics.framework/submit b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/Crashlytics.framework/submit new file mode 100755 index 0000000..b7de4e3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/Crashlytics.framework/submit @@ -0,0 +1,6 @@ +if [[ -z $PODS_ROOT ]]; then +echo "error: The submit binary delivered by cocoapods is in a new location, under '$"{"PODS_ROOT"}"/Crashlytics/submit'. This script was put in place for backwards compatibility, but it relies on PODS_ROOT, which does not have a value in your current setup. Please update the path to the submit binary to fix this issue." +else +echo "warning: The submit script is now located at '$"{"PODS_ROOT"}"/Crashlytics/submit'. To remove this warning, update your path to point to this new location." +sh "${PODS_ROOT}/Crashlytics/submit" "$@" +fi diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/README.md new file mode 100644 index 0000000..2715a06 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/README.md @@ -0,0 +1,39 @@ +![Crashlytics Header](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-crashlytics-header.png) + +Part of [Google Fabric](https://get.fabric.io), [Crashlytics](http://try.crashlytics.com/) offers the most powerful, yet lightest weight crash reporting solution for iOS. Crashlytics also provides real-time analytics through [Answers](https://answers.io/) and app distributions to testers using [Beta](http://try.crashlytics.com/beta/). + +## Setup + +1. Visit [https://fabric.io/sign_up](https://fabric.io/sign_up) to create your Fabric account and to download Fabric.app. + +1. Open Fabric.app, login and select the Crashlytics SDK. + + ![Fabric Plugin](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-fabric-plugin.png) + +1. The Fabric app automatically detects when a project uses CocoaPods and gives you the option to install via the Podfile or Xcode. + + ![Fabric Installation Options](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-pod-installation-option.png) + +1. Select the Podfile option and follow the installation instructions to update your Podfile. **Note:** the Crashlytics Pod includes Answers. If you have Answers included as a separate Pod it should be removed from your Podfile to avoid duplicate symbol errors. + + ``` + pod 'Fabric' + pod 'Crashlytics' + ``` + +1. Run `pod install` + +1. Add a Run Script Build Phase and build your app. + + ![Fabric Run Script Build Phase](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-rsbp.png) + +1. Initialize the SDK by inserting code outlined in the Fabric.app. + +1. Run your app to finish the installation. + +## Resources + +* [Documentation](https://docs.fabric.io/apple/crashlytics/overview.html) +* [Forums](https://stackoverflow.com/questions/tagged/google-fabric) +* [Website](http://try.crashlytics.com/) +* Follow us on Twitter: [@fabric](https://twitter.com/fabric) and [@crashlytics](https://twitter.com/crashlytics) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics new file mode 100755 index 0000000..e5a85e3 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h new file mode 100644 index 0000000..6ec011d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h @@ -0,0 +1,31 @@ +// +// ANSCompatibility.h +// AnswersKit +// +// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. +// + +#pragma once + +#if !__has_feature(nullability) +#define nonnull +#define nullable +#define _Nullable +#define _Nonnull +#endif + +#ifndef NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_BEGIN +#endif + +#ifndef NS_ASSUME_NONNULL_END +#define NS_ASSUME_NONNULL_END +#endif + +#if __has_feature(objc_generics) +#define ANS_GENERIC_NSARRAY(type) NSArray +#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary +#else +#define ANS_GENERIC_NSARRAY(type) NSArray +#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h new file mode 100644 index 0000000..8deacbe --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h @@ -0,0 +1,210 @@ +// +// Answers.h +// Crashlytics +// +// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. +// + +#import +#import "ANSCompatibility.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class exposes the Answers Events API, allowing you to track key + * user user actions and metrics in your app. + */ +@interface Answers : NSObject + +/** + * Log a Sign Up event to see users signing up for your app in real-time, understand how + * many users are signing up with different methods and their success rate signing up. + * + * @param signUpMethodOrNil The method by which a user logged in, e.g. Twitter or Digits. + * @param signUpSucceededOrNil The ultimate success or failure of the login + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logSignUpWithMethod:(nullable NSString *)signUpMethodOrNil + success:(nullable NSNumber *)signUpSucceededOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log an Log In event to see users logging into your app in real-time, understand how many + * users are logging in with different methods and their success rate logging into your app. + * + * @param loginMethodOrNil The method by which a user logged in, e.g. email, Twitter or Digits. + * @param loginSucceededOrNil The ultimate success or failure of the login + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logLoginWithMethod:(nullable NSString *)loginMethodOrNil + success:(nullable NSNumber *)loginSucceededOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Share event to see users sharing from your app in real-time, letting you + * understand what content they're sharing from the type or genre down to the specific id. + * + * @param shareMethodOrNil The method by which a user shared, e.g. email, Twitter, SMS. + * @param contentNameOrNil The human readable name for this piece of content. + * @param contentTypeOrNil The type of content shared. + * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logShareWithMethod:(nullable NSString *)shareMethodOrNil + contentName:(nullable NSString *)contentNameOrNil + contentType:(nullable NSString *)contentTypeOrNil + contentId:(nullable NSString *)contentIdOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log an Invite Event to track how users are inviting other users into + * your application. + * + * @param inviteMethodOrNil The method of invitation, e.g. GameCenter, Twitter, email. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logInviteWithMethod:(nullable NSString *)inviteMethodOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Purchase event to see your revenue in real-time, understand how many users are making purchases, see which + * items are most popular, and track plenty of other important purchase-related metrics. + * + * @param itemPriceOrNil The purchased item's price. + * @param currencyOrNil The ISO4217 currency code. Example: USD + * @param purchaseSucceededOrNil Was the purchase successful or unsuccessful + * @param itemNameOrNil The human-readable form of the item's name. Example: + * @param itemTypeOrNil The type, or genre of the item. Example: Song + * @param itemIdOrNil The machine-readable, unique item identifier Example: SKU + * @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase. + */ ++ (void)logPurchaseWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil + currency:(nullable NSString *)currencyOrNil + success:(nullable NSNumber *)purchaseSucceededOrNil + itemName:(nullable NSString *)itemNameOrNil + itemType:(nullable NSString *)itemTypeOrNil + itemId:(nullable NSString *)itemIdOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Level Start Event to track where users are in your game. + * + * @param levelNameOrNil The level name + * @param customAttributesOrNil A dictionary of custom attributes to associate with this level start event. + */ ++ (void)logLevelStart:(nullable NSString *)levelNameOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Level End event to track how users are completing levels in your game. + * + * @param levelNameOrNil The name of the level completed, E.G. "1" or "Training" + * @param scoreOrNil The score the user completed the level with. + * @param levelCompletedSuccesfullyOrNil A boolean representing whether or not the level was completed successfully. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logLevelEnd:(nullable NSString *)levelNameOrNil + score:(nullable NSNumber *)scoreOrNil + success:(nullable NSNumber *)levelCompletedSuccesfullyOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log an Add to Cart event to see users adding items to a shopping cart in real-time, understand how + * many users start the purchase flow, see which items are most popular, and track plenty of other important + * purchase-related metrics. + * + * @param itemPriceOrNil The purchased item's price. + * @param currencyOrNil The ISO4217 currency code. Example: USD + * @param itemNameOrNil The human-readable form of the item's name. Example: + * @param itemTypeOrNil The type, or genre of the item. Example: Song + * @param itemIdOrNil The machine-readable, unique item identifier Example: SKU + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logAddToCartWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil + currency:(nullable NSString *)currencyOrNil + itemName:(nullable NSString *)itemNameOrNil + itemType:(nullable NSString *)itemTypeOrNil + itemId:(nullable NSString *)itemIdOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Start Checkout event to see users moving through the purchase funnel in real-time, understand how many + * users are doing this and how much they're spending per checkout, and see how it related to other important + * purchase-related metrics. + * + * @param totalPriceOrNil The total price of the cart. + * @param currencyOrNil The ISO4217 currency code. Example: USD + * @param itemCountOrNil The number of items in the cart. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logStartCheckoutWithPrice:(nullable NSDecimalNumber *)totalPriceOrNil + currency:(nullable NSString *)currencyOrNil + itemCount:(nullable NSNumber *)itemCountOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Rating event to see users rating content within your app in real-time and understand what + * content is most engaging, from the type or genre down to the specific id. + * + * @param ratingOrNil The integer rating given by the user. + * @param contentNameOrNil The human readable name for this piece of content. + * @param contentTypeOrNil The type of content shared. + * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logRating:(nullable NSNumber *)ratingOrNil + contentName:(nullable NSString *)contentNameOrNil + contentType:(nullable NSString *)contentTypeOrNil + contentId:(nullable NSString *)contentIdOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Content View event to see users viewing content within your app in real-time and + * understand what content is most engaging, from the type or genre down to the specific id. + * + * @param contentNameOrNil The human readable name for this piece of content. + * @param contentTypeOrNil The type of content shared. + * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logContentViewWithName:(nullable NSString *)contentNameOrNil + contentType:(nullable NSString *)contentTypeOrNil + contentId:(nullable NSString *)contentIdOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Search event allows you to see users searching within your app in real-time and understand + * exactly what they're searching for. + * + * @param queryOrNil The user's query. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. + */ ++ (void)logSearchWithQuery:(nullable NSString *)queryOrNil + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +/** + * Log a Custom Event to see user actions that are uniquely important for your app in real-time, to see how often + * they're performing these actions with breakdowns by different categories you add. Use a human-readable name for + * the name of the event, since this is how the event will appear in Answers. + * + * @param eventName The human-readable name for the event. + * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. Attribute keys + * must be NSString and values must be NSNumber or NSString. + * @discussion How we treat NSNumbers: + * We will provide information about the distribution of values over time. + * + * How we treat NSStrings: + * NSStrings are used as categorical data, allowing comparison across different category values. + * Strings are limited to a maximum length of 100 characters, attributes over this length will be + * truncated. + * + * When tracking the Tweet views to better understand user engagement, sending the tweet's length + * and the type of media present in the tweet allows you to track how tweet length and the type of media influence + * engagement. + */ ++ (void)logCustomEventWithName:(NSString *)eventName + customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h new file mode 100644 index 0000000..1526b0d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h @@ -0,0 +1,33 @@ +// +// CLSAttributes.h +// Crashlytics +// +// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. +// + +#pragma once + +#define CLS_DEPRECATED(x) __attribute__ ((deprecated(x))) + +#if !__has_feature(nullability) + #define nonnull + #define nullable + #define _Nullable + #define _Nonnull +#endif + +#ifndef NS_ASSUME_NONNULL_BEGIN + #define NS_ASSUME_NONNULL_BEGIN +#endif + +#ifndef NS_ASSUME_NONNULL_END + #define NS_ASSUME_NONNULL_END +#endif + +#if __has_feature(objc_generics) + #define CLS_GENERIC_NSARRAY(type) NSArray + #define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary +#else + #define CLS_GENERIC_NSARRAY(type) NSArray + #define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h new file mode 100644 index 0000000..59590d5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h @@ -0,0 +1,64 @@ +// +// CLSLogging.h +// Crashlytics +// +// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. +// +#ifdef __OBJC__ +#import "CLSAttributes.h" +#import + +NS_ASSUME_NONNULL_BEGIN +#endif + + + +/** + * + * The CLS_LOG macro provides as easy way to gather more information in your log messages that are + * sent with your crash data. CLS_LOG prepends your custom log message with the function name and + * line number where the macro was used. If your app was built with the DEBUG preprocessor macro + * defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog. + * If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only. + * + * Example output: + * -[AppDelegate login:] line 134 $ login start + * + * If you would like to change this macro, create a new header file, unset our define and then define + * your own version. Make sure this new header file is imported after the Crashlytics header file. + * + * #undef CLS_LOG + * #define CLS_LOG(__FORMAT__, ...) CLSNSLog... + * + **/ +#ifdef __OBJC__ +#ifdef DEBUG +#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif +#endif + +/** + * + * Add logging that will be sent with your crash data. This logging will not show up in the system.log + * and will only be visible in your Crashlytics dashboard. + * + **/ + +#ifdef __OBJC__ +OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); +OBJC_EXTERN void CLSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0); + +/** + * + * Add logging that will be sent with your crash data. This logging will show up in the system.log + * and your Crashlytics dashboard. It is not recommended for Release builds. + * + **/ +OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); +OBJC_EXTERN void CLSNSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0); + + +NS_ASSUME_NONNULL_END +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h new file mode 100644 index 0000000..a8ff3b0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h @@ -0,0 +1,103 @@ +// +// CLSReport.h +// Crashlytics +// +// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. +// + +#import +#import "CLSAttributes.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate changes for details. + **/ +@protocol CLSCrashReport + +@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, copy, readonly) NSDictionary *customKeys; +@property (nonatomic, copy, readonly) NSString *bundleVersion; +@property (nonatomic, copy, readonly) NSString *bundleShortVersionString; +@property (nonatomic, readonly, nullable) NSDate *crashedOnDate; +@property (nonatomic, copy, readonly) NSString *OSVersion; +@property (nonatomic, copy, readonly) NSString *OSBuildVersion; + +@end + +/** + * The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can + * use this class to get information about the event, and can also set some values after the + * event has occurred. + **/ +@interface CLSReport : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Returns the session identifier for the report. + **/ +@property (nonatomic, copy, readonly) NSString *identifier; + +/** + * Returns the custom key value data for the report. + **/ +@property (nonatomic, copy, readonly) NSDictionary *customKeys; + +/** + * Returns the CFBundleVersion of the application that generated the report. + **/ +@property (nonatomic, copy, readonly) NSString *bundleVersion; + +/** + * Returns the CFBundleShortVersionString of the application that generated the report. + **/ +@property (nonatomic, copy, readonly) NSString *bundleShortVersionString; + +/** + * Returns the date that the report was created. + **/ +@property (nonatomic, copy, readonly) NSDate *dateCreated; + +/** + * Returns the os version that the application crashed on. + **/ +@property (nonatomic, copy, readonly) NSString *OSVersion; + +/** + * Returns the os build version that the application crashed on. + **/ +@property (nonatomic, copy, readonly) NSString *OSBuildVersion; + +/** + * Returns YES if the report contains any crash information, otherwise returns NO. + **/ +@property (nonatomic, assign, readonly) BOOL isCrash; + +/** + * You can use this method to set, after the event, additional custom keys. The rules + * and semantics for this method are the same as those documented in Crashlytics.h. Be aware + * that the maximum size and count of custom keys is still enforced, and you can overwrite keys + * and/or cause excess keys to be deleted by using this method. + **/ +- (void)setObjectValue:(nullable id)value forKey:(NSString *)key; + +/** + * Record an application-specific user identifier. See Crashlytics.h for details. + **/ +@property (nonatomic, copy, nullable) NSString * userIdentifier; + +/** + * Record a user name. See Crashlytics.h for details. + **/ +@property (nonatomic, copy, nullable) NSString * userName; + +/** + * Record a user email. See Crashlytics.h for details. + **/ +@property (nonatomic, copy, nullable) NSString * userEmail; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h new file mode 100644 index 0000000..cdb5596 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h @@ -0,0 +1,38 @@ +// +// CLSStackFrame.h +// Crashlytics +// +// Copyright 2015 Crashlytics, Inc. All rights reserved. +// + +#import +#import "CLSAttributes.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * + * This class is used in conjunction with -[Crashlytics recordCustomExceptionName:reason:frameArray:] to + * record information about non-ObjC/C++ exceptions. All information included here will be displayed + * in the Crashlytics UI, and can influence crash grouping. Be particularly careful with the use of the + * address property. If set, Crashlytics will attempt symbolication and could overwrite other properities + * in the process. + * + **/ +@interface CLSStackFrame : NSObject + ++ (instancetype)stackFrame; ++ (instancetype)stackFrameWithAddress:(NSUInteger)address; ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol; + +@property (nonatomic, copy, nullable) NSString *symbol; +@property (nonatomic, copy, nullable) NSString *rawSymbol; +@property (nonatomic, copy, nullable) NSString *library; +@property (nonatomic, copy, nullable) NSString *fileName; +@property (nonatomic, assign) uint32_t lineNumber; +@property (nonatomic, assign) uint64_t offset; +@property (nonatomic, assign) uint64_t address; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h new file mode 100644 index 0000000..7104ca8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h @@ -0,0 +1,288 @@ +// +// Crashlytics.h +// Crashlytics +// +// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. +// + +#import + +#import "CLSAttributes.h" +#import "CLSLogging.h" +#import "CLSReport.h" +#import "CLSStackFrame.h" +#import "Answers.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol CrashlyticsDelegate; + +/** + * Crashlytics. Handles configuration and initialization of Crashlytics. + * + * Note: The Crashlytics class cannot be subclassed. If this is causing you pain for + * testing, we suggest using either a wrapper class or a protocol extension. + */ +@interface Crashlytics : NSObject + +@property (nonatomic, readonly, copy) NSString *APIKey; +@property (nonatomic, readonly, copy) NSString *version; +@property (nonatomic, assign) BOOL debugMode; + +/** + * + * The delegate can be used to influence decisions on reporting and behavior, as well as reacting + * to previous crashes. + * + * Make certain that the delegate is setup before starting Crashlytics with startWithAPIKey:... or + * via +[Fabric with:...]. Failure to do will result in missing any delegate callbacks that occur + * synchronously during start. + * + **/ +@property (nonatomic, assign, nullable) id delegate; + +/** + * The recommended way to install Crashlytics into your application is to place a call to +startWithAPIKey: + * in your -application:didFinishLaunchingWithOptions: or -applicationDidFinishLaunching: + * method. + * + * Note: Starting with 3.0, the submission process has been significantly improved. The delay parameter + * is no longer required to throttle submissions on launch, performance will be great without it. + * + * @param apiKey The Crashlytics API Key for this app + * + * @return The singleton Crashlytics instance + */ ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey; ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey: instead."); + +/** + * If you need the functionality provided by the CrashlyticsDelegate protocol, you can use + * these convenience methods to activate the framework and set the delegate in one call. + * + * @param apiKey The Crashlytics API Key for this app + * @param delegate A delegate object which conforms to CrashlyticsDelegate. + * + * @return The singleton Crashlytics instance + */ ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id)delegate; ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id)delegate afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey:delegate: instead."); + +/** + * Access the singleton Crashlytics instance. + * + * @return The singleton Crashlytics instance + */ ++ (Crashlytics *)sharedInstance; + +/** + * The easiest way to cause a crash - great for testing! + */ +- (void)crash; + +/** + * The easiest way to cause a crash with an exception - great for testing. + */ +- (void)throwException; + +/** + * Specify a user identifier which will be visible in the Crashlytics UI. + * + * Many of our customers have requested the ability to tie crashes to specific end-users of their + * application in order to facilitate responses to support requests or permit the ability to reach + * out for more information. We allow you to specify up to three separate values for display within + * the Crashlytics UI - but please be mindful of your end-user's privacy. + * + * We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record + * in your system. This could be a database id, hash, or other value that is meaningless to a + * third-party observer but can be indexed and queried by you. + * + * Optionally, you may also specify the end-user's name or username, as well as email address if you + * do not have a system that works well with obscured identifiers. + * + * Pursuant to our EULA, this data is transferred securely throughout our system and we will not + * disseminate end-user data unless required to by law. That said, if you choose to provide end-user + * contact information, we strongly recommend that you disclose this in your application's privacy + * policy. Data privacy is of our utmost concern. + * + * @param identifier An arbitrary user identifier string which ties an end-user to a record in your system. + */ +- (void)setUserIdentifier:(nullable NSString *)identifier; + +/** + * Specify a user name which will be visible in the Crashlytics UI. + * Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs. + * @see setUserIdentifier: + * + * @param name An end user's name. + */ +- (void)setUserName:(nullable NSString *)name; + +/** + * Specify a user email which will be visible in the Crashlytics UI. + * Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs. + * + * @see setUserIdentifier: + * + * @param email An end user's email address. + */ +- (void)setUserEmail:(nullable NSString *)email; + ++ (void)setUserIdentifier:(nullable NSString *)identifier CLS_DEPRECATED("Please access this method via +sharedInstance"); ++ (void)setUserName:(nullable NSString *)name CLS_DEPRECATED("Please access this method via +sharedInstance"); ++ (void)setUserEmail:(nullable NSString *)email CLS_DEPRECATED("Please access this method via +sharedInstance"); + +/** + * Set a value for a for a key to be associated with your crash data which will be visible in the Crashlytics UI. + * When setting an object value, the object is converted to a string. This is typically done by calling + * -[NSObject description]. + * + * @param value The object to be associated with the key + * @param key The key with which to associate the value + */ +- (void)setObjectValue:(nullable id)value forKey:(NSString *)key; + +/** + * Set an int value for a key to be associated with your crash data which will be visible in the Crashlytics UI. + * + * @param value The integer value to be set + * @param key The key with which to associate the value + */ +- (void)setIntValue:(int)value forKey:(NSString *)key; + +/** + * Set an BOOL value for a key to be associated with your crash data which will be visible in the Crashlytics UI. + * + * @param value The BOOL value to be set + * @param key The key with which to associate the value + */ +- (void)setBoolValue:(BOOL)value forKey:(NSString *)key; + +/** + * Set an float value for a key to be associated with your crash data which will be visible in the Crashlytics UI. + * + * @param value The float value to be set + * @param key The key with which to associate the value + */ +- (void)setFloatValue:(float)value forKey:(NSString *)key; + ++ (void)setObjectValue:(nullable id)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); ++ (void)setIntValue:(int)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); ++ (void)setBoolValue:(BOOL)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); ++ (void)setFloatValue:(float)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); + +/** + * This method can be used to record a single exception structure in a report. This is particularly useful + * when your code interacts with non-native languages like Lua, C#, or Javascript. This call can be + * expensive and should only be used shortly before process termination. This API is not intended be to used + * to log NSException objects. All safely-reportable NSExceptions are automatically captured by + * Crashlytics. + * + * @param name The name of the custom exception + * @param reason The reason this exception occurred + * @param frameArray An array of CLSStackFrame objects + */ +- (void)recordCustomExceptionName:(NSString *)name reason:(nullable NSString *)reason frameArray:(CLS_GENERIC_NSARRAY(CLSStackFrame *) *)frameArray; + +/** + * + * This allows you to record a non-fatal event, described by an NSError object. These events will be grouped and + * displayed similarly to crashes. Keep in mind that this method can be expensive. Also, the total number of + * NSErrors that can be recorded during your app's life-cycle is limited by a fixed-size circular buffer. If the + * buffer is overrun, the oldest data is dropped. Errors are relayed to Crashlytics on a subsequent launch + * of your application. + * + * You can also use the -recordError:withAdditionalUserInfo: to include additional context not represented + * by the NSError instance itself. + * + **/ +- (void)recordError:(NSError *)error; +- (void)recordError:(NSError *)error withAdditionalUserInfo:(nullable CLS_GENERIC_NSDICTIONARY(NSString *, id) *)userInfo; + +- (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); +- (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); ++ (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); ++ (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); + +@end + +/** + * + * The CrashlyticsDelegate protocol provides a mechanism for your application to take + * action on events that occur in the Crashlytics crash reporting system. You can make + * use of these calls by assigning an object to the Crashlytics' delegate property directly, + * or through the convenience +startWithAPIKey:delegate: method. + * + */ +@protocol CrashlyticsDelegate +@optional + + +- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:"); +- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id )crash CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:"); + +/** + * + * Called when a Crashlytics instance has determined that the last execution of the + * application resulted in a saved report. This is called synchronously on Crashlytics + * initialization. Your delegate must invoke the completionHandler, but does not need to do so + * synchronously, or even on the main thread. Invoking completionHandler with NO will cause the + * detected report to be deleted and not submitted to Crashlytics. This is useful for + * implementing permission prompts, or other more-complex forms of logic around submitting crashes. + * + * Instead of using this method, you should try to make use of -crashlyticsDidDetectReportForLastExecution: + * if you can. + * + * @warning Failure to invoke the completionHandler will prevent submissions from being reported. Watch out. + * + * @warning Just implementing this delegate method will disable all forms of synchronous report submission. This can + * impact the reliability of reporting crashes very early in application launch. + * + * @param report The CLSReport object representing the last detected report + * @param completionHandler The completion handler to call when your logic has completed. + * + */ +- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report completionHandler:(void (^)(BOOL submit))completionHandler; + +/** + * + * Called when a Crashlytics instance has determined that the last execution of the + * application resulted in a saved report. This method differs from + * -crashlyticsDidDetectReportForLastExecution:completionHandler: in three important ways: + * + * - it is not called synchronously during initialization + * - it does not give you the ability to prevent the report from being submitted + * - the report object itself is immutable + * + * Thanks to these limitations, making use of this method does not impact reporting + * reliabilty in any way. + * + * @param report The read-only CLSReport object representing the last detected report + * + */ + +- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report; + +/** + * If your app is running on an OS that supports it (OS X 10.9+, iOS 7.0+), Crashlytics will submit + * most reports using out-of-process background networking operations. This results in a significant + * improvement in reliability of reporting, as well as power and performance wins for your users. + * If you don't want this functionality, you can disable by returning NO from this method. + * + * @warning Background submission is not supported for extensions on iOS or OS X. + * + * @param crashlytics The Crashlytics singleton instance + * + * @return Return NO if you don't want out-of-process background network operations. + * + */ +- (BOOL)crashlyticsCanUseBackgroundSessions:(Crashlytics *)crashlytics; + +@end + +/** + * `CrashlyticsKit` can be used as a parameter to `[Fabric with:@[CrashlyticsKit]];` in Objective-C. In Swift, use Crashlytics.sharedInstance() + */ +#define CrashlyticsKit [Crashlytics sharedInstance] + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist new file mode 100644 index 0000000..ab886b6 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap new file mode 100644 index 0000000..da0845e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap @@ -0,0 +1,14 @@ +framework module Crashlytics { + header "Crashlytics.h" + header "Answers.h" + header "ANSCompatibility.h" + header "CLSLogging.h" + header "CLSReport.h" + header "CLSStackFrame.h" + header "CLSAttributes.h" + + export * + + link "z" + link "c++" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/run b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/run new file mode 100755 index 0000000..9058ea6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/run @@ -0,0 +1,28 @@ +#!/bin/sh + +# run +# +# Copyright (c) 2015 Crashlytics. All rights reserved. + +# Figure out where we're being called from +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# Quote path in case of spaces or special chars +DIR="\"${DIR}" + +PATH_SEP="/" +VALIDATE_COMMAND="uploadDSYM\" $@ validate run-script" +UPLOAD_COMMAND="uploadDSYM\" $@ run-script" + +# Ensure params are as expected, run in sync mode to validate +eval $DIR$PATH_SEP$VALIDATE_COMMAND +return_code=$? + +if [[ $return_code != 0 ]]; then + exit $return_code +fi + +# Verification passed, upload dSYM in background to prevent Xcode from waiting +# Note: Validation is performed again before upload. +# Output can still be found in Console.app +eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 & diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/submit b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/submit new file mode 100755 index 0000000..3fda5cf Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/submit differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/uploadDSYM b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/uploadDSYM new file mode 100755 index 0000000..6586420 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/iOS/Crashlytics.framework/uploadDSYM differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/submit b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/submit new file mode 100755 index 0000000..3fda5cf Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Crashlytics/submit differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/Fabric.framework/README b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/Fabric.framework/README new file mode 100644 index 0000000..3b1fbe2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/Fabric.framework/README @@ -0,0 +1 @@ +We've now combined all our supported platforms into a single podspec. As a result, we moved our run script to a new location for Cocoapods projects: ${PODS_ROOT}/Fabric/run. To avoid breaking builds that reference the old location of the run script, we've placed this dummy script that calls to the correct location, while providing a helpful warning in Xcode if it is invoked. This bridge for backwards compatibility will be removed in a future release, so please heed the warning! diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/Fabric.framework/run b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/Fabric.framework/run new file mode 100755 index 0000000..b9edd17 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/Fabric.framework/run @@ -0,0 +1,6 @@ +if [[ -z $PODS_ROOT ]]; then + echo "error: The run binary delivered by cocoapods is in a new location, under '$"{"PODS_ROOT"}"/Fabric/run'. This script was put in place for backwards compatibility, but it relies on PODS_ROOT, which does not have a value in your current setup. Please update the path to the run binary to fix this issue." +else + echo "warning: The run script is now located at '$"{"PODS_ROOT"}"/Fabric/run'. To remove this warning, update your Run Script Build Phase to point to this new location." + sh "${PODS_ROOT}/Fabric/run" "$@" +fi diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/README.md new file mode 100644 index 0000000..9eca610 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/README.md @@ -0,0 +1,42 @@ +![Fabric Header](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-fabric-header.png) + +# Fabric + +## Overview + +[Fabric](https://get.fabric.io) provides developers with the tools they need to build the best apps. Developed and maintained by Google and the team that built Crashlytics, Fabric provides an easy way to manage all your SDKs so that you’ll never have to worry about tedious configurations or juggling different accounts. We let you get right into coding and building the next big app. + +For a full list of SDK provided through Fabric visit [https://fabric.io/kits](https://fabric.io/kits). + +## Setup + +The Fabric Pod is a dependency for all Fabric SDKs and is included when installing any Fabric related Pods. General setup instructions are shown below; however, these vary depending on the selected SDK. + +1. Visit [https://fabric.io/sign_up](https://fabric.io/sign_up) to create your Fabric account and to download Fabric.app. + +1. Open Fabric.app, login and select an SDK to install. + + ![Fabric Plugin](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-fabric-plugin.png) + +1. The Fabric app automatically detects when a project uses CocoaPods and gives you the option to install via the Podfile or Xcode. + + ![Fabric Installation Options](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-pod-installation-option.png) + +1. Select the Podfile option and follow the installation instructions to update your Podfile. Note: the example below is for the Crashlytics SDK. The instructions will vary based on the selected SDK. + + ![Fabric Podfile Instructions](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-podfile-instructions.png) + +1. Add a Run Script Build Phase and build your app. + + ![Fabric Run Script Build Phase](https://docs.fabric.io/ios/cocoapod-readmes/cocoapods-rsbp.png) + +1. Initialize the SDK by inserting code outlined in Fabric.app. + +1. Run your app to finish the installation. + +## Resources + +* [Documentation](https://docs.fabric.io/) +* [Forums](https://stackoverflow.com/questions/tagged/google-fabric) +* [Website](https://get.fabric.io) +* Follow us on Twitter: [@fabric](https://twitter.com/fabric) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Fabric b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Fabric new file mode 100755 index 0000000..ffaceb6 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Fabric differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h new file mode 100644 index 0000000..3a9355a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h @@ -0,0 +1,51 @@ +// +// FABAttributes.h +// Fabric +// +// Copyright (C) 2015 Twitter, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#pragma once + +#define FAB_UNAVAILABLE(x) __attribute__((unavailable(x))) + +#if !__has_feature(nullability) + #define nonnull + #define nullable + #define _Nullable + #define _Nonnull +#endif + +#ifndef NS_ASSUME_NONNULL_BEGIN + #define NS_ASSUME_NONNULL_BEGIN +#endif + +#ifndef NS_ASSUME_NONNULL_END + #define NS_ASSUME_NONNULL_END +#endif + + +/** + * The following macros are defined here to provide + * backwards compatability. If you are still using + * them you should migrate to the native nullability + * macros. + */ +#define fab_nullable nullable +#define fab_nonnull nonnull +#define FAB_NONNULL __fab_nonnull +#define FAB_NULLABLE __fab_nullable +#define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN +#define FAB_END_NONNULL NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h new file mode 100644 index 0000000..ecbdb53 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h @@ -0,0 +1,82 @@ +// +// Fabric.h +// Fabric +// +// Copyright (C) 2015 Twitter, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import "FABAttributes.h" + +NS_ASSUME_NONNULL_BEGIN + +#if TARGET_OS_IPHONE +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + #error "Fabric's minimum iOS version is 6.0" +#endif +#else +#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070 + #error "Fabric's minimum OS X version is 10.7" +#endif +#endif + +/** + * Fabric Base. Coordinates configuration and starts all provided kits. + */ +@interface Fabric : NSObject + +/** + * Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use. + * + * For example, in Objective-C: + * + * `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];` + * + * Swift: + * + * `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])` + * + * Only the first call to this method is honored. Subsequent calls are no-ops. + * + * @param kitClasses An array of kit Class objects + * + * @return Returns the shared Fabric instance. In most cases this can be ignored. + */ ++ (instancetype)with:(NSArray *)kitClasses; + +/** + * Returns the Fabric singleton object. + */ ++ (instancetype)sharedSDK; + +/** + * This BOOL enables or disables debug logging, such as kit version information. The default value is NO. + */ +@property (nonatomic, assign) BOOL debug; + +/** + * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. + */ +- (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); + +/** + * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. + */ ++ (instancetype)new FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); + +@end + +NS_ASSUME_NONNULL_END + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Info.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Info.plist new file mode 100644 index 0000000..2b862ba Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Info.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap new file mode 100644 index 0000000..2a31223 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module Fabric { + umbrella header "Fabric.h" + + export * + module * { export * } +} \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/run b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/run new file mode 100755 index 0000000..9058ea6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/run @@ -0,0 +1,28 @@ +#!/bin/sh + +# run +# +# Copyright (c) 2015 Crashlytics. All rights reserved. + +# Figure out where we're being called from +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# Quote path in case of spaces or special chars +DIR="\"${DIR}" + +PATH_SEP="/" +VALIDATE_COMMAND="uploadDSYM\" $@ validate run-script" +UPLOAD_COMMAND="uploadDSYM\" $@ run-script" + +# Ensure params are as expected, run in sync mode to validate +eval $DIR$PATH_SEP$VALIDATE_COMMAND +return_code=$? + +if [[ $return_code != 0 ]]; then + exit $return_code +fi + +# Verification passed, upload dSYM in background to prevent Xcode from waiting +# Note: Validation is performed again before upload. +# Output can still be found in Console.app +eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 & diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/uploadDSYM b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/uploadDSYM new file mode 100755 index 0000000..57114f5 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/iOS/Fabric.framework/uploadDSYM differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/run b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/run new file mode 100755 index 0000000..9058ea6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/run @@ -0,0 +1,28 @@ +#!/bin/sh + +# run +# +# Copyright (c) 2015 Crashlytics. All rights reserved. + +# Figure out where we're being called from +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# Quote path in case of spaces or special chars +DIR="\"${DIR}" + +PATH_SEP="/" +VALIDATE_COMMAND="uploadDSYM\" $@ validate run-script" +UPLOAD_COMMAND="uploadDSYM\" $@ run-script" + +# Ensure params are as expected, run in sync mode to validate +eval $DIR$PATH_SEP$VALIDATE_COMMAND +return_code=$? + +if [[ $return_code != 0 ]]; then + exit $return_code +fi + +# Verification passed, upload dSYM in background to prevent Xcode from waiting +# Note: Validation is performed again before upload. +# Output can still be found in Console.app +eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 & diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/upload-symbols b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/upload-symbols new file mode 100755 index 0000000..a9f011b Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/upload-symbols differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/uploadDSYM b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/uploadDSYM new file mode 100755 index 0000000..57114f5 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Fabric/uploadDSYM differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/CoreOnly/Sources/Firebase.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/CoreOnly/Sources/Firebase.h new file mode 100755 index 0000000..c9f033d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/CoreOnly/Sources/Firebase.h @@ -0,0 +1,150 @@ +#import + +#if !defined(__has_include) + #error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \ + import the headers individually." +#else + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Dynamic Links works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase In App Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif +#endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Performance works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Remote Config works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + +#endif // defined(__has_include) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/CoreOnly/Sources/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/CoreOnly/Sources/module.modulemap new file mode 100755 index 0000000..3685b54 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/CoreOnly/Sources/module.modulemap @@ -0,0 +1,4 @@ +module Firebase { + export * + header "Firebase.h" +} \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/README.md new file mode 100755 index 0000000..20aa692 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Firebase/README.md @@ -0,0 +1,93 @@ +# Firebase APIs for iOS + +Simplify your iOS development, grow your user base, and monetize more +effectively with Firebase services. + +Much more information can be found at [https://firebase.google.com](https://firebase.google.com). + +## Install a Firebase SDK using CocoaPods + +Firebase distributes several iOS specific APIs and SDKs via CocoaPods. +You can install the CocoaPods tool on OS X by running the following command from +the terminal. Detailed information is available in the [Getting Started +guide](https://guides.cocoapods.org/using/getting-started.html#getting-started). + +``` +$ sudo gem install cocoapods +``` + +## Try out an SDK + +You can try any of the SDKs with `pod try`. Run the following command and select +the SDK you are interested in when prompted: + +``` +$ pod try Firebase +``` + +Note that some SDKs may require credentials. More information is available in +the SDK-specific documentation at [https://firebase.google.com/docs/](https://firebase.google.com/docs/). + +## Add a Firebase SDK to your iOS app + +CocoaPods is used to install and manage dependencies in existing Xcode projects. + +1. Create an Xcode project, and save it to your local machine. +2. Create a file named `Podfile` in your project directory. This file defines + your project's dependencies, and is commonly referred to as a Podspec. +3. Open `Podfile`, and add your dependencies. A simple Podspec is shown here: + + ``` + platform :ios, '8.0' + pod 'Firebase' + ``` + +4. Save the file. + +5. Open a terminal and `cd` to the directory containing the Podfile. + + ``` + $ cd /project/ + ``` + +6. Run the `pod install` command. This will install the SDKs specified in the + Podspec, along with any dependencies they may have. + + ``` + $ pod install + ``` + +7. Open your app's `.xcworkspace` file to launch Xcode. Use this file for all + development on your app. + +8. You can also install other Firebase SDKs by adding the subspecs in the + Podfile. + + ``` + pod 'Firebase/AdMob' + pod 'Firebase/Analytics' + pod 'Firebase/Auth' + pod 'Firebase/Database' + pod 'Firebase/DynamicLinks' + pod 'Firebase/Firestore' + pod 'Firebase/Functions' + pod 'Firebase/InAppMessaging' + pod 'Firebase/InAppMessagingDisplay' + pod 'Firebase/Messaging' + pod 'Firebase/MLCommon' + pod 'Firebase/MLModelInterpreter' + pod 'Firebase/MLNLLanguageID' + pod 'Firebase/MLNLSmartReply' + pod 'Firebase/MLNLTranslate' + pod 'Firebase/MLNaturalLanguage' + pod 'Firebase/MLVision' + pod 'Firebase/MLVisionAutoML' + pod 'Firebase/MLVisionBarcodeModel' + pod 'Firebase/MLVisionFaceModel' + pod 'Firebase/MLVisionLabelModel' + pod 'Firebase/MLVisionObjectDetection' + pod 'Firebase/MLVisionTextModel' + pod 'Firebase/Performance' + pod 'Firebase/RemoteConfig' + pod 'Firebase/Storage' + ``` diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector new file mode 100755 index 0000000..58ca891 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap new file mode 100755 index 0000000..270ad21 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap @@ -0,0 +1,10 @@ +framework module FIRAnalyticsConnector { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics new file mode 100755 index 0000000..12f18f9 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h new file mode 100755 index 0000000..d499af6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h @@ -0,0 +1,62 @@ +#import + +#import "FIRAnalytics.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides App Delegate handlers to be used in your App Delegate. + * + * To save time integrating Firebase Analytics in an application, Firebase Analytics does not + * require delegation implementation from the AppDelegate. Instead this is automatically done by + * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App + * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting + * it to NO, and adding the methods in this category to corresponding delegation handlers. + * + * To handle Universal Links, you must return YES in + * [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. + */ +@interface FIRAnalytics (AppDelegate) + +/** + * Handles events related to a URL session that are waiting to be processed. + * + * For optimal use of Firebase Analytics, call this method from the + * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler] + * method of the app delegate in your app. + * + * @param identifier The identifier of the URL session requiring attention. + * @param completionHandler The completion handler to call when you finish processing the events. + * Calling this completion handler lets the system know that your app's user interface is + * updated and a new snapshot can be taken. + */ ++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(nullable void (^)(void))completionHandler; + +/** + * Handles the event when the app is launched by a URL. + * + * Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and + * above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on + * iOS 8.x and below) in your app. + * + * @param url The URL resource to open. This resource can be a network resource or a file. + */ ++ (void)handleOpenURL:(NSURL *)url; + +/** + * Handles the event when the app receives data associated with user activity that includes a + * Universal Link (on iOS 9.0 and above). + * + * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app + * delegate (on iOS 9.0 and above). + * + * @param userActivity The activity object containing the data associated with the task the user + * was performing. + */ ++ (void)handleUserActivity:(id)userActivity; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h new file mode 100755 index 0000000..afb9f82 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h @@ -0,0 +1,132 @@ +#import + +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" + +NS_ASSUME_NONNULL_BEGIN + +/// The top level Firebase Analytics singleton that provides methods for logging events and setting +/// user properties. See the developer guides for general +/// information on using Firebase Analytics in your apps. +NS_SWIFT_NAME(Analytics) +@interface FIRAnalytics : NSObject + +/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have +/// the same parameters. Up to 500 event names are supported. Using predefined events and/or +/// parameters is recommended for optimal reporting. +/// +/// The following event names are reserved and cannot be used: +///

    +///
  • ad_activeview
  • +///
  • ad_click
  • +///
  • ad_exposure
  • +///
  • ad_impression
  • +///
  • ad_query
  • +///
  • adunit_exposure
  • +///
  • app_clear_data
  • +///
  • app_remove
  • +///
  • app_update
  • +///
  • error
  • +///
  • first_open
  • +///
  • in_app_purchase
  • +///
  • notification_dismiss
  • +///
  • notification_foreground
  • +///
  • notification_open
  • +///
  • notification_receive
  • +///
  • os_update
  • +///
  • screen_view
  • +///
  • session_start
  • +///
  • user_engagement
  • +///
+/// +/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or +/// underscores. The name must start with an alphabetic character. Some event names are +/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are +/// case-sensitive and that logging two events whose names differ only in case will result in +/// two distinct events. +/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has +/// no parameters. Parameter names can be up to 40 characters long and must start with an +/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString +/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are +/// supported. NSString parameter values can be up to 100 characters long. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used for parameter names. ++ (void)logEventWithName:(NSString *)name + parameters:(nullable NSDictionary *)parameters + NS_SWIFT_NAME(logEvent(_:parameters:)); + +/// Sets a user property to a given value. Up to 25 user property names are supported. Once set, +/// user property values persist throughout the app lifecycle and across sessions. +/// +/// The following user property names are reserved and cannot be used: +///
    +///
  • first_open_time
  • +///
  • last_deep_link_referrer
  • +///
  • user_id
  • +///
+/// +/// @param value The value of the user property. Values can be up to 36 characters long. Setting the +/// value to nil removes the user property. +/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters +/// or underscores and must start with an alphabetic character. The "firebase_", "google_", and +/// "ga_" prefixes are reserved and should not be used for user property names. ++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name + NS_SWIFT_NAME(setUserProperty(_:forName:)); + +/// Sets the user ID property. This feature must be used in accordance with +/// Google's Privacy Policy +/// +/// @param userID The user ID to ascribe to the user of this app on this device, which must be +/// non-empty and no more than 256 characters long. Setting userID to nil removes the user ID. ++ (void)setUserID:(nullable NSString *)userID; + +/// Sets the current screen name, which specifies the current visual context in your app. This helps +/// identify the areas in your app where users spend their time and how they interact with your app. +/// Must be called on the main thread. +/// +/// Note that screen reporting is enabled automatically and records the class name of the current +/// UIViewController for you without requiring you to call this method. If you implement +/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class +/// will not be automatically tracked. The class name can optionally be overridden by calling this +/// method in the viewDidAppear callback of your UIViewController and specifying the +/// screenClassOverride parameter. setScreenName:screenClass: must be called after +/// [super viewDidAppear:]. +/// +/// If your app does not use a distinct UIViewController for each screen, you should call this +/// method and specify a distinct screenName each time a new screen is presented to the user. +/// +/// The screen name and screen class remain in effect until the current UIViewController changes or +/// a new call to setScreenName:screenClass: is made. +/// +/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil +/// to clear the current screen name. +/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By +/// default this is the class name of the current UIViewController. Set to nil to revert to the +/// default class name. ++ (void)setScreenName:(nullable NSString *)screenName + screenClass:(nullable NSString *)screenClassOverride; + +/// Sets whether analytics collection is enabled for this app on this device. This setting is +/// persisted across app sessions. By default it is enabled. +/// +/// @param analyticsCollectionEnabled A flag that enables or disables Analytics collection. ++ (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets the interval of inactivity in seconds that terminates the current session. The default +/// value is 1800 seconds (30 minutes). +/// +/// @param sessionTimeoutInterval The custom time of inactivity in seconds before the current +/// session terminates. ++ (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval; + +/// The unique ID for this instance of the application. ++ (NSString *)appInstanceID; + +/// Clears all analytics data for this instance from the device and resets the app instance ID. +/// FIRAnalyticsConfiguration values will be reset to the default values. ++ (void)resetAnalyticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h new file mode 100755 index 0000000..c70c53e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h @@ -0,0 +1,407 @@ +/// @file FIREventNames.h +/// +/// Predefined event names. +/// +/// An Event is an important occurrence in your app that you want to measure. You can report up to +/// 500 different types of Events per app and you can associate up to 25 unique parameters with each +/// Event type. Some common events are suggested below, but you may also choose to specify custom +/// Event types that are associated with your specific app. Each event type is identified by a +/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. + +#import + +/// Add Payment Info event. This event signifies that a user has submitted their payment information +/// to your app. +static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) = + @"add_payment_info"; + +/// E-Commerce Add To Cart event. This event signifies that an item was added to a cart for +/// purchase. Add this event to a funnel with kFIREventEcommercePurchase to gauge the effectiveness +/// of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart"; + +/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist. +/// Use this event to identify popular gift items in your app. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) = + @"add_to_wishlist"; + +/// App Open event. By logging this event when an App becomes active, developers can understand how +/// often users leave and return during the course of a Session. Although Sessions are automatically +/// reported, this event can provide further clarification around the continuous engagement of +/// app-users. +static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open"; + +/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of +/// checking out. Add this event to a funnel with your kFIREventEcommercePurchase event to gauge the +/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue +/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue +/// metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) = + @"begin_checkout"; + +/// Campaign Detail event. Log this event to supply the referral details of a re-engagement +/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource, +/// kFIRParameterMedium or kFIRParameterCampaign. Params: +/// +///
    +///
  • @c kFIRParameterSource (NSString)
  • +///
  • @c kFIRParameterMedium (NSString)
  • +///
  • @c kFIRParameterCampaign (NSString)
  • +///
  • @c kFIRParameterTerm (NSString) (optional)
  • +///
  • @c kFIRParameterContent (NSString) (optional)
  • +///
  • @c kFIRParameterAdNetworkClickID (NSString) (optional)
  • +///
  • @c kFIRParameterCP1 (NSString) (optional)
  • +///
+static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) = + @"campaign_details"; + +/// Checkout progress. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString) (optional)
  • +///
+static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) = + @"checkout_progress"; + +/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log +/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy. +/// Params: +/// +///
    +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventEarnVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency"; + +/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note: +/// This is different from the in-app purchase event, which is reported automatically for App +/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also +/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterLocation (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) = + @"ecommerce_purchase"; + +/// Generate Lead event. Log this event when a lead has been generated in the app to understand the +/// efficacy of your install and re-engagement campaigns. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) = + @"generate_lead"; + +/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use +/// this event to analyze how popular certain groups or social features are in your app. Params: +/// +///
    +///
  • @c kFIRParameterGroupID (NSString)
  • +///
+static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group"; + +/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can +/// help you gauge the level distribution of your userbase and help you identify certain levels that +/// are difficult to pass. Params: +/// +///
    +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up"; + +/// Login event. Apps with a login feature can report this event to signify that a user has logged +/// in. +static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login"; + +/// Post Score event. Log this event when the user posts a score in your gaming app. This event can +/// help you understand how users are actually performing in your game and it can help you correlate +/// high scores with certain audiences or behaviors. Params: +/// +///
    +///
  • @c kFIRParameterScore (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score"; + +/// Present Offer event. This event signifies that the app has presented a purchase offer to a user. +/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge +/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) = + @"present_offer"; + +/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
+static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) = + @"purchase_refund"; + +/// Remove from cart event. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) = + @"remove_from_cart"; + +/// Search event. Apps that support search features can use this event to contextualize search +/// operations by supplying the appropriate, corresponding parameters. This event can help you +/// identify the most popular content in your app. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search"; + +/// Select Content event. This general purpose event signifies that a user has selected some content +/// of a certain type in an app. The content can be any object in your app. This event can help you +/// identify popular content and categories of content in your app. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) = + @"select_content"; + +/// Set checkout option. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString)
  • +///
+static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) = + @"set_checkout_option"; + +/// Share event. Apps with social features can log the Share event to identify the most viral +/// content. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share"; + +/// Sign Up event. This event indicates that a user has signed up for an account in your app. The +/// parameter signifies the method by which the user signed up. Use this event to understand the +/// different behaviors between logged in and logged out users. Params: +/// +///
    +///
  • @c kFIRParameterSignUpMethod (NSString)
  • +///
+static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up"; + +/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can +/// help you identify which virtual goods are the most popular objects of purchase. Params: +/// +///
    +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventSpendVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency"; + +/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use +/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this +/// process and move on to the full app experience. +static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) = + @"tutorial_begin"; + +/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding +/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your +/// on-boarding process. +static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) = + @"tutorial_complete"; + +/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your +/// game. Since achievements generally represent the breadth of a gaming experience, this event can +/// help you understand how many users are experiencing all that your game has to offer. Params: +/// +///
    +///
  • @c kFIRParameterAchievementID (NSString)
  • +///
+static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) = + @"unlock_achievement"; + +/// View Item event. This event signifies that some content was shown to the user. This content may +/// be a product, a webpage or just a simple image or text. Use the appropriate parameters to +/// contextualize the event. Use this event to discover the most popular items viewed in your app. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterFlightNumber (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterSearchTerm (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item"; + +/// View Item List event. Log this event when the user has been presented with a list of items of a +/// certain category. Params: +/// +///
    +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
+static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) = + @"view_item_list"; + +/// View Search Results event. Log this event when the user has been presented with the results of a +/// search. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
+static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) = + @"view_search_results"; + +/// Level Start event. Log this event when the user starts a new level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
+static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) = + @"level_start"; + +/// Level End event. Log this event when the user finishes a level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
  • @c kFIRParameterSuccess (NSString)
  • +///
+static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h new file mode 100755 index 0000000..ad9fff7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h @@ -0,0 +1,532 @@ +/// @file FIRParameterNames.h +/// +/// Predefined event parameter names. +/// +/// Params supply information that contextualize Events. You can associate up to 25 unique Params +/// with each Event type. Some Params are suggested below for certain common Events, but you are +/// not limited to these. You may supply extra Params for suggested Events or custom Params for +/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. Param values can +/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and +/// should not be used. + +#import + +/// Game achievement ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) = + @"achievement_id"; + +/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format. +///
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAdNetworkClickID + NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid"; + +/// The store or affiliation from which this transaction occurred (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAffiliation : @"Google Store",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) = + @"affiliation"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Character used in game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) = + @"character"; + +/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutStep : @"1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) = + @"checkout_step"; + +/// Some option on a step in an ecommerce flow (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutOption : @"Visa",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutOption + NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option"; + +/// Campaign content (NSString). +static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content"; + +/// Type of content selected (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) = + @"content_type"; + +/// Coupon code for a purchasable item (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"zz123",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon"; + +/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign. +/// Use varies by network. +///
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1"; + +/// The name of a creative used in a promotional spot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeName : @"Summer Sale",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) = + @"creative_name"; + +/// The name of a creative slot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeSlot : @"summer_banner2",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) = + @"creative_slot"; + +/// Purchase currency in 3-letter +/// ISO_4217 format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) = + @"currency"; + +/// Flight or Travel destination (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) = + @"destination"; + +/// The arrival date, check-out date or rental end date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date"; + +/// Flight number for travel events (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) = + @"flight_number"; + +/// Group/clan/guild ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id"; + +/// Index of an item in a list (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterIndex : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index"; + +/// Item brand (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemBrand : @"Google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) = + @"item_brand"; + +/// Item category (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"t-shirts",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) = + @"item_category"; + +/// Item ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"p7654",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id"; + +/// The Google Place ID (NSString) that +/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemLocationID + NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id"; + +/// Item name (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"abc",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) = + @"item_name"; + +/// The list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemList : @"Search Results",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) = + @"item_list"; + +/// Item variant (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemVariant : @"Red",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) = + @"item_variant"; + +/// Level in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level"; + +/// Location (NSString). The Google Place ID +/// that corresponds to the associated event. Alternatively, you can supply your own custom +/// Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) = + @"location"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// Number of nights staying at hotel (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfNights + NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights"; + +/// Number of passengers traveling (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfPassengers + NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers"; + +/// Number of rooms for travel events (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) = + @"number_of_rooms"; + +/// Flight or Travel origin (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin"; + +/// Purchase price (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price"; + +/// Purchase quantity (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) = + @"quantity"; + +/// Score in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score"; + +/// The search string/keywords used (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) = + @"search_term"; + +/// Shipping cost (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(9.50),
+///       kFIRParameterCurrency : @"USD",  // e.g. $9.50 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) = + @"shipping"; + +/// Sign up method (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// 
+/// +/// This constant has been deprecated. Use Method constant instead. +static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) = + @"sign_up_method"; + +/// A particular approach used in an operation; for example, "facebook" or "email" in the context +/// of a sign_up or login event. (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMethod : @"google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMethod NS_SWIFT_NAME(AnalyticsParameterMethod) = @"method"; + +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The departure date, check-in date or rental start date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) = + @"start_date"; + +/// Tax amount (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax"; + +/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term"; + +/// A single ID for a ecommerce group transaction (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"ab7236dd9823",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) = + @"transaction_id"; + +/// Travel class (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) = + @"travel_class"; + +/// A context-specific numeric value which is accumulated automatically for each event type. This is +/// a general purpose parameter that is useful for accumulating a key metric that pertains to an +/// event. Examples include revenue, distance, time and points. Value should be specified as signed +/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events +/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be +/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is +/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the +/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid +/// currency code for conversion events will cause that +/// conversion to be omitted from reporting. +///
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value"; + +/// Name of virtual currency type (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterVirtualCurrencyName + NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name"; + +/// The name of a level in a game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevelName : @"room_1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) = + @"level_name"; + +/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned +/// integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSuccess : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success"; + +/// Indicates that the associated event should either extend the current session +/// or start a new session if no session was active when the event was logged. +/// Specify YES to extend the current session or to start a new session; any +/// other value will not extend or start a session. +///
+///     NSDictionary *params = @{
+///       kFIRParameterExtendSession : @YES,
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterExtendSession NS_SWIFT_NAME(AnalyticsParameterExtendSession) = + @"extend_session"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h new file mode 100755 index 0000000..132aef7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h @@ -0,0 +1,29 @@ +/// @file FIRUserPropertyNames.h +/// +/// Predefined user property names. +/// +/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can +/// later analyze different behaviors of various segments of your userbase. You may supply up to 25 +/// unique UserProperties per app, and you can use the name and value of your choosing for each one. +/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and +/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to +/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not +/// be used. + +#import + +/// The method used to sign in. For example, "google", "facebook" or "twitter". +static NSString *const kFIRUserPropertySignUpMethod + NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method"; + +/// Indicates whether events logged by Google Analytics can be used to personalize ads for the user. +/// Set to "YES" to enable, or "NO" to disable. Default is enabled. See the +/// documentation for +/// more details and information about related settings. +/// +///
+///     [FIRAnalytics setUserPropertyString:@"NO"
+///                                 forName:kFIRUserPropertyAllowAdPersonalizationSignals];
+/// 
+static NSString *const kFIRUserPropertyAllowAdPersonalizationSignals + NS_SWIFT_NAME(AnalyticsUserPropertyAllowAdPersonalizationSignals) = @"allow_personalized_ads"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h new file mode 100755 index 0000000..ed7588a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h @@ -0,0 +1,5 @@ +#import "FIRAnalytics+AppDelegate.h" +#import "FIRAnalytics.h" +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap new file mode 100755 index 0000000..6118e37 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module FirebaseAnalytics { + umbrella header "FirebaseAnalytics.h" + export * + module * { export * } + link "sqlite3" + link "z" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics new file mode 100755 index 0000000..559016b Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/Modules/module.modulemap new file mode 100755 index 0000000..7bfc4b2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalytics/Frameworks/FirebaseCoreDiagnostics.framework/Modules/module.modulemap @@ -0,0 +1,9 @@ +framework module FirebaseCoreDiagnostics { + export * + module * { export * } + link "z" + link framework "Foundation" + link framework "Security" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h new file mode 100644 index 0000000..a5143c5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInterop.h @@ -0,0 +1,60 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAConditionalUserProperty; +@protocol FIRAnalyticsInteropListener; + +NS_ASSUME_NONNULL_BEGIN + +/// Connector for bridging communication between Firebase SDKs and FirebaseAnalytics API. +@protocol FIRAnalyticsInterop + +/// Sets user property when trigger event is logged. This API is only available in the SDK. +- (void)setConditionalUserProperty:(FIRAConditionalUserProperty *)conditionalUserProperty; + +/// Clears user property if set. +- (void)clearConditionalUserProperty:(NSString *)userPropertyName + clearEventName:(NSString *)clearEventName + clearEventParameters:(NSDictionary *)clearEventParameters; + +/// Returns currently set user properties. +- (NSArray *)conditionalUserProperties:(NSString *)origin + propertyNamePrefix: + (NSString *)propertyNamePrefix; + +/// Returns the maximum number of user properties. +- (NSInteger)maxUserProperties:(NSString *)origin; + +/// Logs events. +- (void)logEventWithOrigin:(NSString *)origin + name:(NSString *)name + parameters:(nullable NSDictionary *)parameters; + +/// Sets user property. +- (void)setUserPropertyWithOrigin:(NSString *)origin name:(NSString *)name value:(id)value; + +/// Registers an Analytics listener for the given origin. +- (void)registerAnalyticsListener:(id)listener + withOrigin:(NSString *)origin; + +/// Unregisters an Analytics listener for the given origin. +- (void)unregisterAnalyticsListenerWithOrigin:(NSString *)origin; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h new file mode 100644 index 0000000..45cde55 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRAnalyticsInteropListener.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// Handles events and messages from Analytics. +@protocol FIRAnalyticsInteropListener + +/// Triggers when an Analytics event happens for the registered origin with +/// `FIRAnalyticsInterop`s `registerAnalyticsListener:withOrigin:`. +- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters; + +@end \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h new file mode 100644 index 0000000..efc54ab --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropEventNames.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// @file FIRInteropEventNames.h + +#import + +/// Notification open event name. +static NSString *const kFIRIEventNotificationOpen = @"_no"; + +/// Notification foreground event name. +static NSString *const kFIRIEventNotificationForeground = @"_nf"; + +/// Campaign event name. +static NSString *const kFIRIEventFirebaseCampaign = @"_cmp"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h new file mode 100644 index 0000000..ae440be --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/Interop/Analytics/Public/FIRInteropParameterNames.h @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// @file FIRInteropParameterNames.h +/// +/// Predefined event parameter names used by Firebase. This file is a subset of the +/// FirebaseAnalytics FIRParameterNames.h public header. +/// +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRIParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRIParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRIParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Message identifier. +static NSString *const kFIRIParameterMessageIdentifier = @"_nmid"; + +/// Message name. +static NSString *const kFIRIParameterMessageName = @"_nmn"; + +/// Message send time. +static NSString *const kFIRIParameterMessageTime = @"_nmt"; + +/// Message device time. +static NSString *const kFIRIParameterMessageDeviceTime = @"_ndt"; + +/// Topic message. +static NSString *const kFIRIParameterTopic = @"_nt"; + +/// Stores the message_id of the last notification opened by the app. +static NSString *const kFIRIUserPropertyLastNotification = @"_ln"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/README.md new file mode 100644 index 0000000..bfaceeb --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseAnalyticsInterop/README.md @@ -0,0 +1,193 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInAppMessagingDisplay, FirebaseMessaging and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +FirebaseAuth, FirebaseCore, FirebaseDatabase and FirebaseStorage now compile, run unit tests, and +work on macOS and tvOS, thanks to contributions from the community. There are a few tweaks needed, +like ensuring iOS-only, macOS-only, or tvOS-only code is correctly guarded with checks for +`TARGET_OS_IOS`, `TARGET_OS_OSX` and `TARGET_OS_TV`. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +For installation instructions, see [above](README.md#accessing-firebase-source-snapshots). + +Note that the Firebase pod is not available for macOS and tvOS. Install a selection of the +`FirebaseAuth`, `FirebaseCore`, `FirebaseDatabase` and `FirebaseStorage` CocoaPods. + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m new file mode 100644 index 0000000..a57936b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m @@ -0,0 +1,62 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "Private/FIRAnalyticsConfiguration.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +@implementation FIRAnalyticsConfiguration +#pragma clang diagnostic pop + ++ (FIRAnalyticsConfiguration *)sharedInstance { + static FIRAnalyticsConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRAnalyticsConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (void)postNotificationName:(NSString *)name value:(id)value { + if (!name.length || !value) { + return; + } + [[NSNotificationCenter defaultCenter] postNotificationName:name + object:self + userInfo:@{name : value}]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled { + [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist { + // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO. + FIRAnalyticsEnabledState analyticsEnabledState = + analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo; + if (shouldPersist) { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:@(analyticsEnabledState) + forKey:kFIRAPersistedConfigMeasurementEnabledStateKey]; + [userDefaults synchronize]; + } + + [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification + value:@(analyticsCollectionEnabled)]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRApp.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRApp.m new file mode 100644 index 0000000..d3b6c46 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRApp.m @@ -0,0 +1,825 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#import "FIRApp.h" +#import "Private/FIRAnalyticsConfiguration.h" +#import "Private/FIRAppInternal.h" +#import "Private/FIRBundleUtil.h" +#import "Private/FIRComponentContainerInternal.h" +#import "Private/FIRConfigurationInternal.h" +#import "Private/FIRLibrary.h" +#import "Private/FIRLogger.h" +#import "Private/FIROptionsInternal.h" + +NSString *const kFIRServiceAdMob = @"AdMob"; +NSString *const kFIRServiceAuth = @"Auth"; +NSString *const kFIRServiceAuthUI = @"AuthUI"; +NSString *const kFIRServiceCrash = @"Crash"; +NSString *const kFIRServiceDatabase = @"Database"; +NSString *const kFIRServiceDynamicLinks = @"DynamicLinks"; +NSString *const kFIRServiceFirestore = @"Firestore"; +NSString *const kFIRServiceFunctions = @"Functions"; +NSString *const kFIRServiceInstanceID = @"InstanceID"; +NSString *const kFIRServiceInvites = @"Invites"; +NSString *const kFIRServiceMessaging = @"Messaging"; +NSString *const kFIRServiceMeasurement = @"Measurement"; +NSString *const kFIRServicePerformance = @"Performance"; +NSString *const kFIRServiceRemoteConfig = @"RemoteConfig"; +NSString *const kFIRServiceStorage = @"Storage"; +NSString *const kGGLServiceAnalytics = @"Analytics"; +NSString *const kGGLServiceSignIn = @"SignIn"; + +NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT"; +NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification"; +NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification"; +NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey"; +NSString *const kFIRAppNameKey = @"FIRAppNameKey"; +NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey"; + +NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat = + @"/google/firebase/global_data_collection_enabled:%@"; +NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey = + @"FirebaseDataCollectionDefaultEnabled"; + +NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification"; + +NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType"; +NSString *const kFIRAppDiagnosticsErrorKey = @"Error"; +NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp"; +NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName"; +NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion"; + +// Auth internal notification notification and key. +NSString *const FIRAuthStateDidChangeInternalNotification = + @"FIRAuthStateDidChangeInternalNotification"; +NSString *const FIRAuthStateDidChangeInternalNotificationAppKey = + @"FIRAuthStateDidChangeInternalNotificationAppKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = + @"FIRAuthStateDidChangeInternalNotificationTokenKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey = + @"FIRAuthStateDidChangeInternalNotificationUIDKey"; + +/** + * The URL to download plist files. + */ +static NSString *const kPlistURL = @"https://console.firebase.google.com/"; + +/** + * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle + * events from Core. + */ +static NSMutableArray> *sRegisteredAsConfigurable; + +@interface FIRApp () + +#ifdef DEBUG +@property(nonatomic) BOOL alreadyOutputDataCollectionFlag; +#endif // DEBUG + +@end + +@implementation FIRApp + +// This is necessary since our custom getter prevents `_options` from being created. +@synthesize options = _options; + +static NSMutableDictionary *sAllApps; +static FIRApp *sDefaultApp; +static NSMutableDictionary *sLibraryVersions; + ++ (void)configure { + FIROptions *options = [FIROptions defaultOptions]; + if (!options) { + // Read the Info.plist to see if the flag is set. At this point we can't check any user defaults + // since the app isn't configured at all, so only rely on the Info.plist value. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue == nil || [collectionEnabledPlistValue boolValue]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore), + kFIRAppDiagnosticsErrorKey : [FIRApp errorForMissingOptions] + }]; + } + + [NSException raise:kFirebaseCoreErrorDomain + format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find " + @"a valid GoogleService-Info.plist in your project. Please download one " + @"from %@.", + kPlistURL]; + } + [FIRApp configureWithOptions:options]; +#if TARGET_OS_OSX || TARGET_OS_TV + FIRLogNotice(kFIRLoggerCore, @"I-COR000028", + @"tvOS and macOS SDK support is not part of the official Firebase product. " + @"Instead they are community supported. Details at " + @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md."); +#endif +} + ++ (void)configureWithOptions:(FIROptions *)options { + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Options is nil. Please pass a valid options."]; + } + [FIRApp configureWithName:kFIRDefaultAppName options:options]; +} + ++ (void)configureWithName:(NSString *)name options:(FIROptions *)options { + if (!name || !options) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."]; + } + if (name.length == 0) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."]; + } + + if ([name isEqualToString:kFIRDefaultAppName]) { + if (sDefaultApp) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Default app has already been configured."]; + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app."); + } else { + // Validate the app name and ensure it hasn't been configured already. + for (NSUInteger charIndex = 0; charIndex < name.length; charIndex++) { + char character = [name characterAtIndex:charIndex]; + if (!((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || character == '_' || character == '-')) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App name can only contain alphanumeric (A-Z,a-z,0-9), " + @"hyphen (-), and underscore (_) characters"]; + } + } + + @synchronized(self) { + if (sAllApps && sAllApps[name]) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", name]; + } + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name); + } + + @synchronized(self) { + FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options]; + if (app.isDefaultApp) { + sDefaultApp = app; + } + + [FIRApp addAppToAppDictionary:app]; + [FIRApp sendNotificationsToSDKs:app]; + } +} + ++ (FIRApp *)defaultApp { + if (sDefaultApp) { + return sDefaultApp; + } + FIRLogError(kFIRLoggerCore, @"I-COR000003", + @"The default Firebase app has not yet been " + @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your " + @"application initialization. Read more: https://goo.gl/ctyzm8."); + return nil; +} + ++ (FIRApp *)appNamed:(NSString *)name { + @synchronized(self) { + if (sAllApps) { + FIRApp *app = sAllApps[name]; + if (app) { + return app; + } + } + FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name); + return nil; + } +} + ++ (NSDictionary *)allApps { + @synchronized(self) { + if (!sAllApps) { + FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet."); + } + return [sAllApps copy]; + } +} + +// Public only for tests ++ (void)resetApps { + @synchronized(self) { + sDefaultApp = nil; + [sAllApps removeAllObjects]; + sAllApps = nil; + [sLibraryVersions removeAllObjects]; + sLibraryVersions = nil; + } +} + +- (void)deleteApp:(FIRAppVoidBoolCallback)completion { + @synchronized([self class]) { + if (sAllApps && sAllApps[self.name]) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name); + + // Remove all cached instances from the container before deleting the app. + [self.container removeAllCachedInstances]; + + [sAllApps removeObjectForKey:self.name]; + [self clearDataCollectionSwitchFromUserDefaults]; + if ([self.name isEqualToString:kFIRDefaultAppName]) { + sDefaultApp = nil; + } + NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name}; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification + object:[self class] + userInfo:appInfoDict]; + completion(YES); + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist."); + completion(NO); + } + } +} + ++ (void)addAppToAppDictionary:(FIRApp *)app { + if (!sAllApps) { + sAllApps = [NSMutableDictionary dictionary]; + } + if ([app configureCore]) { + sAllApps[app.name] = app; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in " + @"GoogleService-Info.plist or set in the customized options."]; + } +} + +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options { + self = [super init]; + if (self) { + _name = [name copy]; + _options = [options copy]; + _options.editingLocked = YES; + _isDefaultApp = [name isEqualToString:kFIRDefaultAppName]; + _container = [[FIRComponentContainer alloc] initWithApp:self]; + } + return self; +} + +- (BOOL)configureCore { + [self checkExpectedBundleID]; + if (![self isAppIDValid]) { + if (_options.usingOptionsFromDefaultPlist && [self isDataCollectionDefaultEnabled]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore), + kFIRAppDiagnosticsErrorKey : [FIRApp errorForInvalidAppID], + }]; + } + return NO; + } + + if ([self isDataCollectionDefaultEnabled]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore), + kFIRAppDiagnosticsFIRAppKey : self + }]; + } + +#if TARGET_OS_IOS + // Initialize the Analytics once there is a valid options under default app. Analytics should + // always initialize first by itself before the other SDKs. + if ([self.name isEqualToString:kFIRDefaultAppName]) { + Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics"); + if (firAnalyticsClass) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:); +#pragma clang diagnostic pop + if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [firAnalyticsClass performSelector:startWithConfigurationSelector + withObject:[FIRConfiguration sharedInstance].analyticsConfiguration + withObject:_options]; +#pragma clang diagnostic pop + } + } + } +#endif + + return YES; +} + +- (FIROptions *)options { + return [_options copy]; +} + +- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled { +#ifdef DEBUG + FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.", + dataCollectionDefaultEnabled ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; +#endif // DEBUG + + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key]; + + // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set + // within FIROptions and change the Analytics value if necessary. Analytics only works with the + // default app, so return if this isn't the default app. + if (!self.isDefaultApp) { + return; + } + + // Check if the Analytics flag is explicitly set. If so, no further actions are necessary. + if ([self.options isAnalyticsCollectionExpicitlySet]) { + return; + } + + // The Analytics flag has not been explicitly set, so update with the value being set. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[FIRAnalyticsConfiguration sharedInstance] + setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled + persistSetting:NO]; +#pragma clang diagnostic pop +} + +- (BOOL)isDataCollectionDefaultEnabled { + // Check if it's been manually set before in code, and use that as the higher priority value. + NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self]; + if (defaultsObject != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.", + [defaultsObject boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [defaultsObject boolValue]; + } + + // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`. + // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has + // no performance impact calling multiple times. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.", + [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [collectionEnabledPlistValue boolValue]; + } + +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set."); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return YES; +} + +#pragma mark - private + ++ (void)sendNotificationsToSDKs:(FIRApp *)app { + // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`. + NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp]; + NSDictionary *appInfoDict = @{ + kFIRAppNameKey : app.name, + kFIRAppIsDefaultAppKey : isDefaultApp, + kFIRGoogleAppIDKey : app.options.googleAppID + }; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification + object:self + userInfo:appInfoDict]; + + // This is the new way of sending information to SDKs. + // TODO: Do we want this on a background thread, maybe? + @synchronized(self) { + for (Class library in sRegisteredAsConfigurable) { + [library configureWithApp:app]; + } + } +} + ++ (NSError *)errorForMissingOptions { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : + @"Unable to parse GoogleService-Info.plist in order to configure services.", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidPlistFile + userInfo:errorDict]; +} + ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", service]; + NSDictionary *errorDict = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + return [NSError errorWithDomain:domain code:code userInfo:errorDict]; +} + ++ (NSError *)errorForInvalidAppID { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : @"Unable to validate Google App ID", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the " + @"customized options." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidAppID + userInfo:errorDict]; +} + ++ (BOOL)isDefaultAppConfigured { + return (sDefaultApp != nil); +} + ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version { + // Create the set of characters which aren't allowed, only if this feature is used. + NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedSet addCharactersInString:@"-_."]; + NSCharacterSet *disallowedSet = [allowedSet invertedSet]; + // Make sure the library name and version strings do not contain unexpected characters, and + // add the name/version pair to the dictionary. + if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound && + [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) { + @synchronized(self) { + if (!sLibraryVersions) { + sLibraryVersions = [[NSMutableDictionary alloc] init]; + } + sLibraryVersions[name] = version; + } + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000027", + @"The library name (%@) or version number (%@) contain invalid characters. " + @"Only alphanumeric, dash, underscore and period characters are allowed.", + name, version); + } +} + ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version { + // This is called at +load time, keep the work to a minimum. + + // Ensure the class given conforms to the proper protocol. + if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] || + ![(Class)library respondsToSelector:@selector(componentsToRegister)]) { + [NSException raise:NSInvalidArgumentException + format:@"Class %@ attempted to register components, but it does not conform to " + @"`FIRLibrary or provide a `componentsToRegister:` method.", + library]; + } + + [FIRComponentContainer registerAsComponentRegistrant:library]; + if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRegisteredAsConfigurable = [[NSMutableArray alloc] init]; + }); + @synchronized(self) { + [sRegisteredAsConfigurable addObject:library]; + } + } + [self registerLibrary:name withVersion:version]; +} + ++ (NSString *)firebaseUserAgent { + @synchronized(self) { + NSMutableArray *libraries = + [[NSMutableArray alloc] initWithCapacity:sLibraryVersions.count]; + for (NSString *libraryName in sLibraryVersions) { + [libraries addObject:[NSString stringWithFormat:@"%@/%@", libraryName, + sLibraryVersions[libraryName]]]; + } + [libraries sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + return [libraries componentsJoinedByString:@" "]; + } +} + +- (void)checkExpectedBundleID { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *expectedBundleID = [self expectedBundleID]; + // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for + // backward compatibility. + if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID + inBundles:bundles]) { + FIRLogError(kFIRLoggerCore, @"I-COR000008", + @"The project's Bundle ID is inconsistent with " + @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are " + @"using a customized options. To ensure that everything can be configured " + @"correctly, you may need to make the Bundle IDs consistent. To continue with this " + @"plist file, you may change your app's bundle identifier to '%@'. Or you can " + @"download a new configuration file that matches your bundle identifier from %@ " + @"and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + } +} + +#pragma mark - private - App ID Validation + +/** + * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file. + * This is the main method for validating app ID. + * + * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise. + */ +- (BOOL)isAppIDValid { + NSString *appID = _options.googleAppID; + BOOL isValid = [FIRApp validateAppID:appID]; + if (!isValid) { + NSString *expectedBundleID = [self expectedBundleID]; + FIRLogError(kFIRLoggerCore, @"I-COR000009", + @"The GOOGLE_APP_ID either in the plist file " + @"'%@.%@' or the one set in the customized options is invalid. If you are using " + @"the plist file, use the iOS version of bundle identifier to download the file, " + @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle " + @"identifier to '%@'. Or you can download a new configuration file that matches " + @"your bundle identifier from %@ and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + }; + return isValid; +} + ++ (BOOL)validateAppID:(NSString *)appID { + // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not + // have a valid fingerprint, otherwise we just warn about the potential issue. + if (!appID.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + NSString *appIDVersion; + if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] + intoString:&appIDVersion]) { + return NO; + } + + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + NSArray *knownVersions = @[ @"1" ]; + if (![knownVersions containsObject:appIDVersion]) { + // Permit unknown yet properly formatted app ID versions. + FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion); + return YES; + } + + if (![self validateAppIDFormat:appID withVersion:appIDVersion]) { + return NO; + } + + if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) { + return NO; + } + + return YES; +} + ++ (NSString *)actualBundleID { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +/** + * Validates that the format of the app ID string is what is expected based on the supplied version. + * The version must end in ":". + * + * For v1 app ids the format is expected to be + * '::ios:'. + * + * This method does not verify that the contents of the app id are correct, just that they fulfill + * the expected format. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected format, NO otherwise. + */ ++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { + if (!appID.length || !version.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + // Skip version part + // '**::ios:' + if (![stringScanner scanString:version intoString:NULL]) { + // The version part is missing or mismatched + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '*:*:ios:' + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':**:ios:'. + NSInteger projectNumber = NSNotFound; + if (![stringScanner scanInteger:&projectNumber]) { + // NO project number found. + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':*:*ios:'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The project number must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::*ios*:'. + NSString *platform; + if (![stringScanner scanUpToString:@":" intoString:&platform]) { + return NO; + } + + if (![platform isEqualToString:@"ios"]) { + // The platform must be @"ios" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios*:*'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The platform must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios:**'. + unsigned long long fingerprint = NSNotFound; + if (![stringScanner scanHexLongLong:&fingerprint]) { + // Fingerprint part is missing + return NO; + } + + if (!stringScanner.isAtEnd) { + // There are not allowed characters in the fingerprint part + return NO; + } + + return YES; +} + +/** + * Validates that the fingerprint of the app ID string is what is expected based on the supplied + * version. + * + * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected fingerprint and the version is known, NO + * otherwise. + */ ++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version { + // Extract the supplied fingerprint from the supplied app ID. + // This assumes the app ID format is the same for all known versions below. If the app ID format + // changes in future versions, the tokenizing of the app ID format will need to take into account + // the version of the app ID. + NSArray *components = [appID componentsSeparatedByString:@":"]; + if (components.count != 4) { + return NO; + } + + NSString *suppliedFingerprintString = components[3]; + if (!suppliedFingerprintString.length) { + return NO; + } + + uint64_t suppliedFingerprint; + NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString]; + if (![scanner scanHexLongLong:&suppliedFingerprint]) { + return NO; + } + + if ([version isEqual:@"1"]) { + // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated. + return YES; + } + + // Unknown version. + return NO; +} + +- (NSString *)expectedBundleID { + return _options.bundleID; +} + +// end App ID validation + +#pragma mark - Reading From Plist & User Defaults + +/** + * Clears the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ +- (void)clearDataCollectionSwitchFromUserDefaults { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +/** + * Reads the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app { + // Read the object in user defaults, and only return if it's an NSNumber. + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name]; + id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key]; + if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) { + return collectionEnabledDefaultsObject; + } + + return nil; +} + +/** + * Reads the data collection switch from the Info.plist for easier testing and readability. Will + * only read once from the plist and return the cached value. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromPlist { + static NSNumber *collectionEnabledPlistObject; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber. + id plistValue = [[NSBundle mainBundle] + objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey]; + if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) { + collectionEnabledPlistObject = (NSNumber *)plistValue; + } + }); + + return collectionEnabledPlistObject; +} + +#pragma mark - Sending Logs + +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error { + // If the user has manually turned off data collection, return and don't send logs. + if (![self isDataCollectionDefaultEnabled]) { + return; + } + + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ + kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeSDK), + kFIRAppDiagnosticsSDKNameKey : serviceName, + kFIRAppDiagnosticsSDKVersionKey : version, + kFIRAppDiagnosticsFIRAppKey : self + }]; + if (error) { + userInfo[kFIRAppDiagnosticsErrorKey] = error; + } + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDiagnosticsNotification + object:nil + userInfo:userInfo]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m new file mode 100644 index 0000000..2aecdab --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m @@ -0,0 +1,47 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRAppAssociationRegistration.h" + +#import + +@implementation FIRAppAssociationRegistration + ++ (nullable id)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(id _Nullable (^)(void))creationBlock { + @synchronized(self) { + SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:); + NSMutableDictionary *objectsByKey = objc_getAssociatedObject(host, dictKey); + if (!objectsByKey) { + objectsByKey = [[NSMutableDictionary alloc] init]; + objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + id obj = objectsByKey[key]; + NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey]; + if (obj) { + if ([creationBlockBeingCalled isEqual:obj]) { + [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed" + format:@"host: %@ key: %@", host, key]; + } + return obj; + } + objectsByKey[key] = creationBlockBeingCalled; + obj = creationBlock(); + objectsByKey[key] = obj; + return obj; + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m new file mode 100644 index 0000000..841833a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m @@ -0,0 +1,75 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRBundleUtil.h" + +#import + +@implementation FIRBundleUtil + ++ (NSArray *)relevantBundles { + return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ]; +} + ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles { + // Loop through all bundles to find the config dict. + for (NSBundle *bundle in bundles) { + NSString *path = [bundle pathForResource:resourceName ofType:fileType]; + // Use the first one we find. + if (path) { + return path; + } + } + return nil; +} + ++ (NSArray *)relevantURLSchemes { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (NSBundle *bundle in [[self class] relevantBundles]) { + NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]; + for (NSDictionary *urlType in urlTypes) { + [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]]; + } + } + return result; +} + ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles { + for (NSBundle *bundle in bundles) { + // This allows app extensions that have the app's bundle as their prefix to pass this test. + NSString *applicationBundleIdentifier = + [GULAppEnvironmentUtil isAppExtension] + ? [self bundleIdentifierByRemovingLastPartFrom:bundleIdentifier] + : bundleIdentifier; + + if ([applicationBundleIdentifier isEqualToString:bundle.bundleIdentifier]) { + return YES; + } + } + return NO; +} + ++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponent.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponent.m new file mode 100644 index 0000000..2474d1a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponent.m @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRComponent.h" + +#import "Private/FIRComponentContainer.h" +#import "Private/FIRDependency.h" + +@interface FIRComponent () + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock; + +@end + +@implementation FIRComponent + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; +} + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:instantiationTiming + dependencies:dependencies + creationBlock:creationBlock]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + self = [super init]; + if (self) { + _protocol = protocol; + _instantiationTiming = instantiationTiming; + _dependencies = [dependencies copy]; + _creationBlock = creationBlock; + } + return self; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m new file mode 100644 index 0000000..1977d0e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m @@ -0,0 +1,176 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRComponentContainer.h" + +#import "Private/FIRAppInternal.h" +#import "Private/FIRComponent.h" +#import "Private/FIRLibrary.h" +#import "Private/FIRLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer () + +/// The dictionary of components that are registered for a particular app. The key is an NSString +/// of the protocol. +@property(nonatomic, strong) NSMutableDictionary *components; + +/// Cached instances of components that requested to be cached. +@property(nonatomic, strong) NSMutableDictionary *cachedInstances; + +@end + +@implementation FIRComponentContainer + +// Collection of all classes that register to provide components. +static NSMutableSet *sFIRComponentRegistrants; + +#pragma mark - Public Registration + ++ (void)registerAsComponentRegistrant:(Class)klass { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sFIRComponentRegistrants = [[NSMutableSet alloc] init]; + }); + + [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants]; +} + ++ (void)registerAsComponentRegistrant:(Class)klass + inSet:(NSMutableSet *)allRegistrants { + [allRegistrants addObject:klass]; +} + +#pragma mark - Internal Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWithApp:app registrants:sFIRComponentRegistrants]; +} + +- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet *)allRegistrants { + self = [super init]; + if (self) { + _app = app; + _cachedInstances = [NSMutableDictionary dictionary]; + _components = [NSMutableDictionary dictionary]; + + [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app]; + } + return self; +} + +- (void)populateComponentsFromRegisteredClasses:(NSSet *)classes forApp:(FIRApp *)app { + // Loop through the verified component registrants and populate the components array. + for (Class klass in classes) { + // Loop through all the components being registered and store them as appropriate. + // Classes which do not provide functionality should use a dummy FIRComponentRegistrant + // protocol. + for (FIRComponent *component in [klass componentsToRegister]) { + // Check if the component has been registered before, and error out if so. + NSString *protocolName = NSStringFromProtocol(component.protocol); + if (self.components[protocolName]) { + FIRLogError(kFIRLoggerCore, @"I-COR000029", + @"Attempted to register protocol %@, but it already has an implementation.", + protocolName); + continue; + } + + // Store the creation block for later usage. + self.components[protocolName] = component.creationBlock; + + // Instantiate the + BOOL shouldInstantiateEager = + (component.instantiationTiming == FIRInstantiationTimingAlwaysEager); + BOOL shouldInstantiateDefaultEager = + (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp && + [app isDefaultApp]); + if (shouldInstantiateEager || shouldInstantiateDefaultEager) { + [self instantiateInstanceForProtocol:component.protocol withBlock:component.creationBlock]; + } + } + } +} + +#pragma mark - Instance Creation + +/// Instantiate an instance of a class that conforms to the specified protocol. +/// This will: +/// - Call the block to create an instance if possible, +/// - Validate that the instance returned conforms to the protocol it claims to, +/// - Cache the instance if the block requests it +- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol + withBlock:(FIRComponentCreationBlock)creationBlock { + if (!creationBlock) { + return nil; + } + + // Create an instance using the creation block. + BOOL shouldCache = NO; + id instance = creationBlock(self, &shouldCache); + if (!instance) { + return nil; + } + + // An instance was created, validate that it conforms to the protocol it claims to. + NSString *protocolName = NSStringFromProtocol(protocol); + if (![instance conformsToProtocol:protocol]) { + FIRLogError(kFIRLoggerCore, @"I-COR000030", + @"An instance conforming to %@ was requested, but the instance provided does not " + @"conform to the protocol", + protocolName); + } + + // The instance is ready to be returned, but check if it should be cached first before returning. + if (shouldCache) { + self.cachedInstances[protocolName] = instance; + } + + return instance; +} + +#pragma mark - Internal Retrieval + +- (nullable id)instanceForProtocol:(Protocol *)protocol { + // Check if there is a cached instance, and return it if so. + NSString *protocolName = NSStringFromProtocol(protocol); + id cachedInstance = self.cachedInstances[protocolName]; + if (cachedInstance) { + return cachedInstance; + } + + // Use the creation block to instantiate an instance and return it. + FIRComponentCreationBlock creationBlock = self.components[protocolName]; + return [self instantiateInstanceForProtocol:protocol withBlock:creationBlock]; +} + +#pragma mark - Lifecycle + +- (void)removeAllCachedInstances { + // Loop through the cache and notify each instance that is a maintainer to clean up after itself. + for (id instance in self.cachedInstances.allValues) { + if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] && + [instance respondsToSelector:@selector(appWillBeDeleted:)]) { + [instance appWillBeDeleted:self.app]; + } + } + + [self.cachedInstances removeAllObjects]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m new file mode 100644 index 0000000..bdc004f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRComponentType.h" + +#import "Private/FIRComponentContainerInternal.h" + +@implementation FIRComponentType + ++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container { + // Forward the call to the container. + return [container instanceForProtocol:protocol]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m new file mode 100644 index 0000000..869f73d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m @@ -0,0 +1,46 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRConfigurationInternal.h" + +#import "Private/FIRAnalyticsConfiguration.h" + +extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +@implementation FIRConfiguration + ++ (instancetype)sharedInstance { + static FIRConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance]; + } + return self; +} + +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel { + NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin, + @"Invalid logger level, %ld", (long)loggerLevel); + FIRSetLoggerLevel(loggerLevel); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRDependency.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRDependency.m new file mode 100644 index 0000000..f979984 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRDependency.m @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Private/FIRDependency.h" + +@interface FIRDependency () + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +@end + +@implementation FIRDependency + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol { + return [[self alloc] initWithProtocol:protocol isRequired:YES]; +} + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + return [[self alloc] initWithProtocol:protocol isRequired:required]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + self = [super init]; + if (self) { + _protocol = protocol; + _isRequired = required; + } + return self; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRErrors.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRErrors.m new file mode 100644 index 0000000..72120c5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRErrors.m @@ -0,0 +1,21 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRErrors.h" + +NSString *const kFirebaseErrorDomain = @"com.firebase"; +NSString *const kFirebaseConfigErrorDomain = @"com.firebase.config"; +NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core"; +NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf"; +NSString *const kFirebaseStorageErrorDomain = @"com.firebase.storage"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRLogger.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRLogger.m new file mode 100644 index 0000000..532a96c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRLogger.m @@ -0,0 +1,179 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRLogger.h" + +#import +#import +#import + +#import "Private/FIRVersion.h" + +FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]"; + +// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones! +FIRLoggerService kFIRLoggerABTesting = @"[Firebase/ABTesting]"; +FIRLoggerService kFIRLoggerAdMob = @"[Firebase/AdMob]"; +FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]"; +FIRLoggerService kFIRLoggerAuth = @"[Firebase/Auth]"; +FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]"; +FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]"; +FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]"; +FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]"; + +/// Arguments passed on launch. +NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled"; +NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled"; +NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR"; + +/// Key for the debug mode bit in NSUserDefaults. +NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode"; + +/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults` +/// will be used. +static NSUserDefaults *sFIRLoggerUserDefaults; + +static dispatch_once_t sFIRLoggerOnceToken; + +// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled +// flags used by Analytics. Users who use those flags expect Analytics to log verbosely, +// while the rest of Firebase logs at the default level. This flag is introduced to support +// that behavior. +static BOOL sFIRAnalyticsDebugMode; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void FIRLoggerInitializeASL() { + dispatch_once(&sFIRLoggerOnceToken, ^{ + // Register Firebase Version with GULLogger. + GULLoggerRegisterVersion(FIRVersionString); + + // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in. + NSArray *arguments = [NSProcessInfo processInfo].arguments; + BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument]; + + // Use the standard NSUserDefaults if it hasn't been explicitly set. + if (sFIRLoggerUserDefaults == nil) { + sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults]; + } + + BOOL forceDebugMode = NO; + BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey]; + if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) { // Default mode + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] || + debugMode) { // Debug mode + [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey]; + forceDebugMode = YES; + } + GULLoggerInitializeASL(); + if (overrideSTDERR) { + GULLoggerEnableSTDERR(); + } + if (forceDebugMode) { + GULLoggerForceDebug(); + } + }); +} + +__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) { + sFIRAnalyticsDebugMode = analyticsDebugMode; +} + +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) { + FIRLoggerInitializeASL(); + GULSetLoggerLevel((GULLoggerLevel)loggerLevel); +} + +#ifdef DEBUG +void FIRResetLogger() { + extern void GULResetLogger(void); + sFIRLoggerOnceToken = 0; + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + sFIRLoggerUserDefaults = nil; + GULResetLogger(); +} + +void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) { + sFIRLoggerUserDefaults = defaults; +} +#endif + +/** + * Check if the level is high enough to be loggable. + * + * Analytics can override the log level with an intentional race condition. + * Add the attribute to get a clean thread sanitizer run. + */ +__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, + BOOL analyticsComponent) { + FIRLoggerInitializeASL(); + if (sFIRAnalyticsDebugMode && analyticsComponent) { + return YES; + } + return GULIsLoggableLevel((GULLoggerLevel)loggerLevel); +} + +void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + FIRLoggerInitializeASL(); + GULLogBasic((GULLoggerLevel)level, service, + sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode, + message, args_ptr); +} + +/** + * Generates the logging functions using macros. + * + * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure blah failed. + * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure succeed. + */ +#define FIR_LOGGING_FUNCTION(level) \ + void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +FIR_LOGGING_FUNCTION(Error) +FIR_LOGGING_FUNCTION(Warning) +FIR_LOGGING_FUNCTION(Notice) +FIR_LOGGING_FUNCTION(Info) +FIR_LOGGING_FUNCTION(Debug) + +#undef FIR_MAKE_LOGGER + +#pragma mark - FIRLoggerWrapper + +@implementation FIRLoggerWrapper + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + FIRLogBasic(level, service, messageCode, message, args); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIROptions.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIROptions.m new file mode 100644 index 0000000..3e6a3a0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIROptions.m @@ -0,0 +1,448 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/FIRAppInternal.h" +#import "Private/FIRBundleUtil.h" +#import "Private/FIRErrors.h" +#import "Private/FIRLogger.h" +#import "Private/FIROptionsInternal.h" +#import "Private/FIRVersion.h" + +// Keys for the strings in the plist file. +NSString *const kFIRAPIKey = @"API_KEY"; +NSString *const kFIRTrackingID = @"TRACKING_ID"; +NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID"; +NSString *const kFIRClientID = @"CLIENT_ID"; +NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID"; +NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID"; +NSString *const kFIRDatabaseURL = @"DATABASE_URL"; +NSString *const kFIRStorageBucket = @"STORAGE_BUCKET"; +// The key to locate the expected bundle identifier in the plist file. +NSString *const kFIRBundleID = @"BUNDLE_ID"; +// The key to locate the project identifier in the plist file. +NSString *const kFIRProjectID = @"PROJECT_ID"; + +NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED"; + +NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED"; +NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED"; + +// Library version ID formatted like: +// @"5" // Major version (one or more digits) +// @"04" // Minor version (exactly 2 digits) +// @"01" // Build number (exactly 2 digits) +// @"000"; // Fixed "000" +NSString *kFIRLibraryVersionID; + +// Plist file name. +NSString *const kServiceInfoFileName = @"GoogleService-Info"; +// Plist file type. +NSString *const kServiceInfoFileType = @"plist"; + +// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp. +NSString *const kFIRExceptionBadModification = + @"Attempted to modify options after it's set on FIRApp. Please modify all properties before " + @"initializing FIRApp."; + +@interface FIROptions () + +/** + * This property maintains the actual configuration key-value pairs. + */ +@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary; + +/** + * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary. + * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the main plist override values from the GoogleService-Info.plist. + */ +@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary; + +/** + * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the infoDictionary override values from the GoogleService-Info.plist. + */ +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary; + +/** + * Throw exception if editing is locked when attempting to modify an option. + */ +- (void)checkEditingLocked; + +@end + +@implementation FIROptions { + /// Backing variable for self.analyticsOptionsDictionary. + NSDictionary *_analyticsOptionsDictionary; +} + +static FIROptions *sDefaultOptions = nil; +static NSDictionary *sDefaultOptionsDictionary = nil; + +#pragma mark - Public only for internal class methods + ++ (FIROptions *)defaultOptions { + if (sDefaultOptions != nil) { + return sDefaultOptions; + } + + NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary]; + if (defaultOptionsDictionary == nil) { + return nil; + } + + sDefaultOptions = [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary]; + return sDefaultOptions; +} + +#pragma mark - Private class methods + ++ (void)initialize { + // Report FirebaseCore version for useragent string + [FIRApp registerLibrary:@"fire-ios" + withVersion:[NSString stringWithUTF8String:FIRCoreVersionString]]; + + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + NSString *xcodeVersion = info[@"DTXcodeBuild"]; + NSString *sdkVersion = info[@"DTSDKBuild"]; + if (xcodeVersion) { + [FIRApp registerLibrary:@"xcode" withVersion:xcodeVersion]; + } + if (sdkVersion) { + [FIRApp registerLibrary:@"apple-sdk" withVersion:sdkVersion]; + } +} + ++ (NSDictionary *)defaultOptionsDictionary { + if (sDefaultOptionsDictionary != nil) { + return sDefaultOptionsDictionary; + } + NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName]; + if (plistFilePath == nil) { + return nil; + } + sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath]; + if (sDefaultOptionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000011", + @"The configuration file is not a dictionary: " + @"'%@.%@'.", + kServiceInfoFileName, kServiceInfoFileType); + } + return sDefaultOptionsDictionary; +} + +// Returns the path of the plist file with a given file name. ++ (NSString *)plistFilePathWithName:(NSString *)fileName { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *plistFilePath = + [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName + andFileType:kServiceInfoFileType + inBundles:bundles]; + if (plistFilePath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.", + fileName, kServiceInfoFileType); + } + return plistFilePath; +} + ++ (void)resetDefaultOptions { + sDefaultOptions = nil; + sDefaultOptionsDictionary = nil; +} + +#pragma mark - Private instance methods + +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary { + self = [super init]; + if (self) { + _optionsDictionary = [optionsDictionary mutableCopy]; + _usingOptionsFromDefaultPlist = YES; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + FIROptions *newOptions = [[[self class] allocWithZone:zone] init]; + if (newOptions) { + newOptions.optionsDictionary = self.optionsDictionary; + newOptions.deepLinkURLScheme = self.deepLinkURLScheme; + newOptions.editingLocked = self.isEditingLocked; + newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist; + } + return newOptions; +} + +#pragma mark - Public instance methods + +- (instancetype)initWithContentsOfFile:(NSString *)plistPath { + self = [super init]; + if (self) { + if (plistPath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil."); + return nil; + } + _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy]; + if (_optionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000014", + @"The configuration file at %@ does not exist or " + @"is not a well-formed plist file.", + plistPath); + return nil; + } + // TODO: Do we want to validate the dictionary here? It says we do that already in + // the public header. + } + return self; +} + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary]; + [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID]; + [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID]; + [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID]; + self.optionsDictionary = mutableOptionsDict; + } + return self; +} + +- (NSString *)APIKey { + return self.optionsDictionary[kFIRAPIKey]; +} + +- (void)checkEditingLocked { + if (self.isEditingLocked) { + [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification]; + } +} + +- (void)setAPIKey:(NSString *)APIKey { + [self checkEditingLocked]; + _optionsDictionary[kFIRAPIKey] = [APIKey copy]; +} + +- (NSString *)clientID { + return self.optionsDictionary[kFIRClientID]; +} + +- (void)setClientID:(NSString *)clientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRClientID] = [clientID copy]; +} + +- (NSString *)trackingID { + return self.optionsDictionary[kFIRTrackingID]; +} + +- (void)setTrackingID:(NSString *)trackingID { + [self checkEditingLocked]; + _optionsDictionary[kFIRTrackingID] = [trackingID copy]; +} + +- (NSString *)GCMSenderID { + return self.optionsDictionary[kFIRGCMSenderID]; +} + +- (void)setGCMSenderID:(NSString *)GCMSenderID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy]; +} + +- (NSString *)projectID { + return self.optionsDictionary[kFIRProjectID]; +} + +- (void)setProjectID:(NSString *)projectID { + [self checkEditingLocked]; + _optionsDictionary[kFIRProjectID] = [projectID copy]; +} + +- (NSString *)androidClientID { + return self.optionsDictionary[kFIRAndroidClientID]; +} + +- (void)setAndroidClientID:(NSString *)androidClientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy]; +} + +- (NSString *)googleAppID { + return self.optionsDictionary[kFIRGoogleAppID]; +} + +- (void)setGoogleAppID:(NSString *)googleAppID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy]; +} + +- (NSString *)libraryVersionID { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The unit tests are set up to catch anything that does not properly convert. + NSString *version = [NSString stringWithUTF8String:FIRCoreVersionString]; + NSArray *components = [version componentsSeparatedByString:@"."]; + NSString *major = [components objectAtIndex:0]; + NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]]; + NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]]; + kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch]; + }); + return kFIRLibraryVersionID; +} + +- (void)setLibraryVersionID:(NSString *)libraryVersionID { + _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy]; +} + +- (NSString *)databaseURL { + return self.optionsDictionary[kFIRDatabaseURL]; +} + +- (void)setDatabaseURL:(NSString *)databaseURL { + [self checkEditingLocked]; + + _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy]; +} + +- (NSString *)storageBucket { + return self.optionsDictionary[kFIRStorageBucket]; +} + +- (void)setStorageBucket:(NSString *)storageBucket { + [self checkEditingLocked]; + _optionsDictionary[kFIRStorageBucket] = [storageBucket copy]; +} + +- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme { + [self checkEditingLocked]; + _deepLinkURLScheme = [deepLinkURLScheme copy]; +} + +- (NSString *)bundleID { + return self.optionsDictionary[kFIRBundleID]; +} + +- (void)setBundleID:(NSString *)bundleID { + [self checkEditingLocked]; + _optionsDictionary[kFIRBundleID] = [bundleID copy]; +} + +#pragma mark - Internal instance methods + +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary { + if (_analyticsOptionsDictionary == nil) { + NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init]; + NSArray *measurementKeys = @[ + kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled, + kFIRIsAnalyticsCollectionDeactivated + ]; + for (NSString *key in measurementKeys) { + id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil; + if (!value) { + continue; + } + tempAnalyticsOptions[key] = value; + } + _analyticsOptionsDictionary = tempAnalyticsOptions; + } + return _analyticsOptionsDictionary; +} + +- (NSDictionary *)analyticsOptionsDictionary { + return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary]; +} + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still + * be supported. + */ +- (BOOL)isMeasurementEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (value == nil) { + // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have + // to check if it's the default app. The FIROptions instance can't be modified after + // `+configure` is called, so it's not a good place to copy it either in case the flag is + // changed at runtime. + + // If no values are set for Analytics, fall back to the global collection switch in FIRApp. + // Analytics only supports the default FIRApp, so check that first. + if (![FIRApp isDefaultAppConfigured]) { + return NO; + } + + // Fall back to the default app's collection switch when the key is not in the dictionary. + return [FIRApp defaultApp].isDataCollectionDefaultEnabled; + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionExpicitlySet { + // If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication + // that the developer wants FirebaseAnalytics enabled so continue checking. + if (self.isAnalyticsCollectionDeactivated) { + return YES; + } + + // Check if the current Analytics flag is set. + id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // Check if the old measurement flag is set. + id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // No flags are set to explicitly enable or disable FirebaseAnalytics. + return NO; +} + +- (BOOL)isAnalyticsCollectionEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (value == nil) { + return self.isMeasurementEnabled; // Fall back to older plist flag. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionDeactivated { + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated]; + if (value == nil) { + return NO; // Analytics Collection is not deactivated when the key is not in the dictionary. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsEnabled { + return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue]; +} + +- (BOOL)isSignInEnabled { + return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRVersion.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRVersion.m new file mode 100644 index 0000000..ec0f6ba --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/FIRVersion.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_VERSION +#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation" +#endif + +#ifndef FIRCore_VERSION +#error "FIRCore_VERSION is not defined: add -DFIRCore_VERSION=... to the build invocation" +#endif + +// The following two macros supply the incantation so that the C +// preprocessor does not try to parse the version as a floating +// point number. See +// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/ +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRVersionString = (const char *const)STR(Firebase_VERSION); +const char *const FIRCoreVersionString = (const char *const)STR(FIRCore_VERSION); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h new file mode 100644 index 0000000..6429ac7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// Values stored in analyticsEnabledState. Never alter these constants since they must match with +/// values persisted to disk. +typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) { + // 0 is the default value for keys not found stored in persisted config, so it cannot represent + // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet. + kFIRAnalyticsEnabledStateNotSet = 0, + kFIRAnalyticsEnabledStateSetYes = 1, + kFIRAnalyticsEnabledStateSetNo = 2, +}; + +/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads +/// measurementEnabledState using this same key. +static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey = + @"/google/measurement/measurement_enabled_state"; + +static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification = + @"FIRAnalyticsConfigurationSetEnabledNotification"; +static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification = + @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification"; +static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification = + @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification"; + +@interface FIRAnalyticsConfiguration : NSObject + +/// Returns the shared instance of FIRAnalyticsConfiguration. ++ (FIRAnalyticsConfiguration *)sharedInstance; + +// Sets whether analytics collection is enabled for this app on this device. This setting is +// persisted across app sessions. By default it is enabled. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist +/// the value or not. The setting should not be persisted if being set by the global data collection +/// flag. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h new file mode 100644 index 0000000..3fc69c6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// TODO: Remove this once Auth moves over to Core's instance registration system. +/** @class FIRAppAssociationRegistration + @brief Manages object associations as a singleton-dependent: At most one object is + registered for any given host/key pair, and the object shall be created on-the-fly when + asked for. + */ +@interface FIRAppAssociationRegistration : NSObject + +/** @fn registeredObjectWithHost:key:creationBlock: + @brief Retrieves the registered object with a particular host and key. + @param host The host object. + @param key The key to specify the registered object on the host. + @param creationBlock The block to return the object to be registered if not already. + The block is executed immediately before this method returns if it is executed at all. + It can also be executed multiple times across different method invocations if previous + execution of the block returns @c nil. + @return The registered object for the host/key pair, or @c nil if no object is registered + and @c creationBlock returns @c nil. + @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this + method again within the @c creationBlock with the same host/key pair raises an exception. + The registered object is retained by the host. + */ ++ (nullable ObjectType)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(ObjectType _Nullable (^)(void))creationBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h new file mode 100644 index 0000000..09728cd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h @@ -0,0 +1,180 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +/** + * Names of services provided by Firebase. + */ +extern NSString *const kFIRServiceAdMob; +extern NSString *const kFIRServiceAuth; +extern NSString *const kFIRServiceAuthUI; +extern NSString *const kFIRServiceDatabase; +extern NSString *const kFIRServiceDynamicLinks; +extern NSString *const kFIRServiceInstanceID; +extern NSString *const kFIRServiceMessaging; +extern NSString *const kFIRServiceMeasurement; +extern NSString *const kFIRServiceRemoteConfig; +extern NSString *const kFIRServiceStorage; + +/** + * Names of services provided by the Google pod, but logged by the Firebase pod. + */ +extern NSString *const kGGLServiceAnalytics; +extern NSString *const kGGLServiceSignIn; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h new file mode 100644 index 0000000..d9475dd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * This class provides utilities for accessing resources in bundles. + */ +@interface FIRBundleUtil : NSObject + +/** + * Finds all relevant bundles, starting with [NSBundle mainBundle]. + */ ++ (NSArray *)relevantBundles; + +/** + * Reads the options dictionary from one of the provided bundles. + * + * @param resourceName The resource name, e.g. @"GoogleService-Info". + * @param fileType The file type (extension), e.g. @"plist". + * @param bundles The bundles to expect, in priority order. See also + * +[FIRBundleUtil relevantBundles]. + */ ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles; + +/** + * Finds URL schemes defined in all relevant bundles, starting with those from + * [NSBundle mainBundle]. + */ ++ (NSArray *)relevantURLSchemes; + +/** + * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension + * suffixes). + */ ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h new file mode 100644 index 0000000..cb51ee7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h new file mode 100644 index 0000000..f3dc356 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FIRComponentType.h" +#import "FIRLibrary.h" + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h new file mode 100644 index 0000000..e8552fa --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h @@ -0,0 +1,43 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FIRComponent.h" +#import "FIRComponentContainer.h" + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer (Private) + +/// Initializes a contain for a given app. This should only be called by the app itself. +- (instancetype)initWithApp:(FIRApp *)app; + +/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the +/// protocol wasn't registered, or if the instance couldn't instantiate for the provided app. +- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:)); + +/// Remove all of the cached instances stored and allow them to clean up after themselves. +- (void)removeAllCachedInstances; + +/// Register a class to provide components for the interoperability system. The class should conform +/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects. ++ (void)registerAsComponentRegistrant:(Class)klass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h new file mode 100644 index 0000000..6f2aca7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h new file mode 100644 index 0000000..ee16886 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRConfiguration.h" + +@class FIRAnalyticsConfiguration; + +@interface FIRConfiguration () + +/** + * The configuration class for Firebase Analytics. This should be removed once the logic for + * enabling and disabling Analytics is moved to Analytics. + */ +@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h new file mode 100644 index 0000000..46e9b7e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h new file mode 100644 index 0000000..f77b3d0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h new file mode 100644 index 0000000..19e4732 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h new file mode 100644 index 0000000..728c062 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import +#import "FIRComponent.h" + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h new file mode 100644 index 0000000..548e389 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h new file mode 100644 index 0000000..117efda --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h @@ -0,0 +1,114 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExpicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h new file mode 100644 index 0000000..226efb1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The version of the Firebase SDK. */ +FOUNDATION_EXPORT const char *const FIRVersionString; + +/** The version of the FirebaseCore Component. */ +FOUNDATION_EXPORT const char *const FIRCoreVersionString; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h new file mode 100644 index 0000000..e0dd6d6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h @@ -0,0 +1,127 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** A block that takes a BOOL and has no return value. */ +typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback); + +/** + * The entry point of Firebase SDKs. + * + * Initialize and configure FIRApp using +[FIRApp configure] + * or other customized ways as shown below. + * + * The logging system has two modes: default mode and debug mode. In default mode, only logs with + * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent + * to device. The log levels that Firebase uses are consistent with the ASL log levels. + * + * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this + * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled, + * further executions of the application will also be in debug mode. In order to return to default + * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled. + * + * It is also possible to change the default logging level in code by calling setLoggerLevel: on + * the FIRConfiguration interface. + */ +NS_SWIFT_NAME(FirebaseApp) +@interface FIRApp : NSObject + +/** + * Configures a default Firebase app. Raises an exception if any configuration step fails. The + * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched + * and before using Firebase services. This method is thread safe and contains synchronous file I/O + * (reading GoogleService-Info.plist from disk). + */ ++ (void)configure; + +/** + * Configures the default Firebase app with the provided options. The default app is named + * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread + * safe. + * + * @param options The Firebase application options used to configure the service. + */ ++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:)); + +/** + * Configures a Firebase app with the given name and options. Raises an exception if any + * configuration step fails. This method is thread safe. + * + * @param name The application's name given by the developer. The name should should only contain + Letters, Numbers and Underscore. + * @param options The Firebase application options used to configure the services. + */ +// clang-format off ++ (void)configureWithName:(NSString *)name + options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:)); +// clang-format on + +/** + * Returns the default app, or nil if the default app does not exist. + */ ++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app()); + +/** + * Returns a previously created FIRApp instance with the given name, or nil if no such app exists. + * This method is thread safe. + */ ++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:)); + +/** + * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This + * method is thread safe. + */ +@property(class, readonly, nullable) NSDictionary *allApps; + +/** + * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for + * future use. This method is thread safe. + */ +- (void)deleteApp:(FIRAppVoidBoolCallback)completion; + +/** + * FIRApp instances should not be initialized directly. Call +[FIRApp configure], + * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Gets the name of this app. + */ +@property(nonatomic, copy, readonly) NSString *name; + +/** + * Gets a copy of the options for this app. These are non-modifiable. + */ +@property(nonatomic, copy, readonly) FIROptions *options; + +/** + * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES` + * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value + * is persisted across runs of the app so that it can be set once when users have consented to + * collection. + */ +@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled) + BOOL dataCollectionDefaultEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h new file mode 100644 index 0000000..8de3b07 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This interface provides global level properties that the developer can tweak. + */ +NS_SWIFT_NAME(FirebaseConfiguration) +@interface FIRConfiguration : NSObject + +/** Returns the shared configuration object. */ +@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared); + +/** + * Sets the logging level for internal Firebase logging. Firebase will only log messages + * that are logged at or below loggerLevel. The messages are logged both to the Xcode + * console and to the device's log. Note that if an app is running from AppStore, it will + * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose) + * setting. + * + * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice. + */ +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h new file mode 100644 index 0000000..dca3aa0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note that importing GULLoggerLevel.h will lead to a non-modular header +// import error. + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, FIRLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + FIRLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + FIRLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + FIRLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + FIRLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + FIRLoggerLevelDebug = 7, + /** Minimum log level. */ + FIRLoggerLevelMin = FIRLoggerLevelError, + /** Maximum log level. */ + FIRLoggerLevelMax = FIRLoggerLevelDebug +} NS_SWIFT_NAME(FirebaseLoggerLevel); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h new file mode 100644 index 0000000..87a01dd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h @@ -0,0 +1,116 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class provides constant fields of Google APIs. + */ +NS_SWIFT_NAME(FirebaseOptions) +@interface FIROptions : NSObject + +/** + * Returns the default options. The first time this is called it synchronously reads + * GoogleService-Info.plist from disk. + */ ++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions()); + +/** + * An iOS API key used for authenticating requests from your app, e.g. + * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers. + */ +@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey); + +/** + * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set + * manually or in a plist. + */ +@property(nonatomic, copy) NSString *bundleID; + +/** + * The OAuth2 client ID for iOS application used to authenticate Google users, for example + * @"12345.apps.googleusercontent.com", used for signing in with Google. + */ +@property(nonatomic, copy, nullable) NSString *clientID; + +/** + * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics. + */ +@property(nonatomic, copy, nullable) NSString *trackingID; + +/** + * The Project Number from the Google Developer's console, for example @"012345678901", used to + * configure Google Cloud Messaging. + */ +@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID); + +/** + * The Project ID from the Firebase console, for example @"abc-xyz-123". + */ +@property(nonatomic, copy, nullable) NSString *projectID; + +/** + * The Android client ID used in Google AppInvite when an iOS app has its Android version, for + * example @"12345.apps.googleusercontent.com". + */ +@property(nonatomic, copy, nullable) NSString *androidClientID; + +/** + * The Google App ID that is used to uniquely identify an instance of an app. + */ +@property(nonatomic, copy) NSString *googleAppID; + +/** + * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com". + */ +@property(nonatomic, copy, nullable) NSString *databaseURL; + +/** + * The URL scheme used to set up Durable Deep Link service. + */ +@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme; + +/** + * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com". + */ +@property(nonatomic, copy, nullable) NSString *storageBucket; + +/** + * Initializes a customized instance of FIROptions from the file at the given plist file path. This + * will read the file synchronously from disk. + * For example, + * NSString *filePath = + * [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]; + * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; + * Returns nil if the plist file does not exist or is invalid. + */ +- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath; + +/** + * Initializes a customized instance of FIROptions with required fields. Use the mutable properties + * to modify fields for configuring specific services. + */ +// clang-format off +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + GCMSenderID:(NSString *)GCMSenderID + NS_SWIFT_NAME(init(googleAppID:gcmSenderID:)); +// clang-format on + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h new file mode 100644 index 0000000..95119ae --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseCore/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h new file mode 100644 index 0000000..fadde02 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h @@ -0,0 +1,160 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// The format of the debug code will show in the log as: e.g. +// for code 1000, it will show as I-IID001000. +typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) { + // DO NOT USE 2000, 2002. + kFIRInstanceIDMessageCodeFIRApp000 = 1000, // I-IID001000 + kFIRInstanceIDMessageCodeFIRApp001 = 1001, + kFIRInstanceIDMessageCodeFIRApp002 = 1002, + kFIRInstanceIDMessageCodeInternal001 = 2001, + kFIRInstanceIDMessageCodeInternal002 = 2002, + // FIRInstanceID.m + // DO NOT USE 4000. + kFIRInstanceIDMessageCodeInstanceID000 = 3000, + kFIRInstanceIDMessageCodeInstanceID001 = 3001, + kFIRInstanceIDMessageCodeInstanceID002 = 3002, + kFIRInstanceIDMessageCodeInstanceID003 = 3003, + kFIRInstanceIDMessageCodeInstanceID004 = 3004, + kFIRInstanceIDMessageCodeInstanceID005 = 3005, + kFIRInstanceIDMessageCodeInstanceID006 = 3006, + kFIRInstanceIDMessageCodeInstanceID007 = 3007, + kFIRInstanceIDMessageCodeInstanceID008 = 3008, + kFIRInstanceIDMessageCodeInstanceID009 = 3009, + kFIRInstanceIDMessageCodeInstanceID010 = 3010, + kFIRInstanceIDMessageCodeInstanceID011 = 3011, + kFIRInstanceIDMessageCodeInstanceID012 = 3012, + kFIRInstanceIDMessageCodeInstanceID013 = 3013, + kFIRInstanceIDMessageCodeInstanceID014 = 3014, + kFIRInstanceIDMessageCodeInstanceID015 = 3015, + kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016, + // FIRInstanceIDAuthService.m + kFIRInstanceIDMessageCodeAuthService000 = 5000, + kFIRInstanceIDMessageCodeAuthService001 = 5001, + kFIRInstanceIDMessageCodeAuthService002 = 5002, + kFIRInstanceIDMessageCodeAuthService003 = 5003, + kFIRInstanceIDMessageCodeAuthService004 = 5004, + kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress = 5004, + + // FIRInstanceIDBackupExcludedPlist.m + kFIRInstanceIDMessageCodeBackupExcludedPlist000 = 6000, + kFIRInstanceIDMessageCodeBackupExcludedPlist001 = 6001, + kFIRInstanceIDMessageCodeBackupExcludedPlist002 = 6002, + kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum = 6003, + // FIRInstanceIDCheckinService.m + kFIRInstanceIDMessageCodeService000 = 7000, + kFIRInstanceIDMessageCodeService001 = 7001, + kFIRInstanceIDMessageCodeService002 = 7002, + kFIRInstanceIDMessageCodeService003 = 7003, + kFIRInstanceIDMessageCodeService004 = 7004, + kFIRInstanceIDMessageCodeService005 = 7005, + kFIRInstanceIDMessageCodeService006 = 7006, + kFIRIntsanceIDInvalidNetworkSession = 7007, + // FIRInstanceIDCheckinStore.m + // DO NOT USE 8002, 8004 - 8008 + kFIRInstanceIDMessageCodeCheckinStore000 = 8000, + kFIRInstanceIDMessageCodeCheckinStore001 = 8001, + kFIRInstanceIDMessageCodeCheckinStore003 = 8003, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted = 8009, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved = 8010, + // FIRInstanceIDKeyPair.m + // DO NOT USE 9001, 9003 + kFIRInstanceIDMessageCodeKeyPair000 = 9000, + kFIRInstanceIDMessageCodeKeyPair002 = 9002, + kFIRInstanceIDMessageCodeKeyPairMigrationError = 9004, + kFIRInstanceIDMessageCodeKeyPairMigrationSuccess = 9005, + kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair = 9006, + + // FIRInstanceIDKeyPairStore.m + kFIRInstanceIDMessageCodeKeyPairStore000 = 10000, + kFIRInstanceIDMessageCodeKeyPairStore001 = 10001, + kFIRInstanceIDMessageCodeKeyPairStore002 = 10002, + kFIRInstanceIDMessageCodeKeyPairStore003 = 10003, + kFIRInstanceIDMessageCodeKeyPairStore004 = 10004, + kFIRInstanceIDMessageCodeKeyPairStore005 = 10005, + kFIRInstanceIDMessageCodeKeyPairStore006 = 10006, + kFIRInstanceIDMessageCodeKeyPairStore007 = 10007, + kFIRInstanceIDMessageCodeKeyPairStore008 = 10008, + kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair = 10009, + // FIRInstanceIDKeyPairUtilities.m + kFIRInstanceIDMessageCodeKeyPairUtilities000 = 11000, + kFIRInstanceIDMessageCodeKeyPairUtilities001 = 11001, + kFIRInstanceIDMessageCodeKeyPairUtilitiesFirstConcatenateParamNil = 11002, + + // DO NOT USE 12000 - 12014 + + // FIRInstanceIDStore.m + // DO NOT USE 13004, 13005, 13007, 13008, 13010, 13011, 13013, 13014 + kFIRInstanceIDMessageCodeStore000 = 13000, + kFIRInstanceIDMessageCodeStore001 = 13001, + kFIRInstanceIDMessageCodeStore002 = 13002, + kFIRInstanceIDMessageCodeStore003 = 13003, + kFIRInstanceIDMessageCodeStore006 = 13006, + kFIRInstanceIDMessageCodeStore009 = 13009, + kFIRInstanceIDMessageCodeStore012 = 13012, + // FIRInstanceIDTokenManager.m + // DO NOT USE 14002, 14005 + kFIRInstanceIDMessageCodeTokenManager000 = 14000, + kFIRInstanceIDMessageCodeTokenManager001 = 14001, + kFIRInstanceIDMessageCodeTokenManager003 = 14003, + kFIRInstanceIDMessageCodeTokenManager004 = 14004, + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset = 14006, + kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset = 14007, + kFIRInstanceIDMessageCodeTokenManagerSavedAppVersion = 14008, + kFIRInstanceIDMessageCodeTokenManagerErrorInvalidatingAllTokens = 14009, + kFIRInstanceIDMessageCodeTokenManagerAPNSChanged = 14010, + kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated = 14011, + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken = 14012, + // FIRInstanceIDTokenStore.m + // DO NOT USE 15002 - 15013 + kFIRInstanceIDMessageCodeTokenStore000 = 15000, + kFIRInstanceIDMessageCodeTokenStore001 = 15001, + kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo = 15015, + + // DO NOT USE 16000, 18004 + + // FIRInstanceIDUtilities.m + kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier = 18000, + kFIRInstanceIDMessageCodeUtilitiesAppEnvironmentUtilNotAvailable = 18001, + kFIRInstanceIDMessageCodeUtilitiesCannotGetHardwareModel = 18002, + kFIRInstanceIDMessageCodeUtilitiesCannotGetSystemVersion = 18003, + // FIRInstanceIDTokenOperation.m + kFIRInstanceIDMessageCodeTokenOperationFailedToSignParams = 19000, + // FIRInstanceIDTokenFetchOperation.m + // DO NOT USE 20004, 20005 + kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest = 20000, + kFIRInstanceIDMessageCodeTokenFetchOperationRequestError = 20001, + kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse = 20002, + kFIRInstanceIDMessageCodeTokenFetchOperationBadTokenStructure = 20003, + // FIRInstanceIDTokenDeleteOperation.m + kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest = 21000, + kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError = 21001, + kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse = 21002, + // FIRInstanceIDTokenInfo.m + kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo = 22000, + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged = 22001, + kFIRInstanceIDMessageCodeTokenInfoLocaleChanged = 22002, + // FIRInstanceIDKeychain.m + kFIRInstanceIDKeychainReadItemError = 23000, + kFIRInstanceIDKeychainAddItemError = 23001, + kFIRInstanceIDKeychainDeleteItemError = 23002, + kFIRInstanceIDKeychainCreateKeyPairError = 23003, + kFIRInstanceIDKeychainUpdateItemError = 23004, + +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h new file mode 100644 index 0000000..3e3ec17 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import "FIRInstanceIDCheckinService.h" + +/** + * Internal API used by Firebase SDK teams by calling in reflection or internal teams. + */ +// TODO(chliangGoogle) Rename this to Internal. +@interface FIRInstanceID (Private) + +/** + * Return the cached checkin preferences on the disk. This is used internally only by Messaging. + * + * @return The cached checkin preferences on the client. + */ +- (nullable FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Fetches checkin info for the app. If the app has valid cached checkin preferences + * they are returned instead of making a network request. + * + * @param handler The completion handler to invoke once the request has completed. + */ +- (void)fetchCheckinInfoWithHandler:(nullable FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Get the InstanceID for the app. If an ID was created before and cached + * successfully we will return that ID. If no cached ID exists we create + * a new ID, cache it and return that. + * + * This is a blocking call and should not really be called on the main thread. + * + * @param error The error object that represents the error while trying to + * retrieve the instance id. + * + * @return The InstanceID for the app. + */ +- (nullable NSString *)appInstanceID:(NSError *_Nullable *_Nullable)error; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m new file mode 100644 index 0000000..61d43a4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID+Private.h" + +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDKeyPairStore.h" +#import "FIRInstanceIDTokenManager.h" + +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readonly, strong) FIRInstanceIDKeyPairStore *keyPairStore; + +@end + +@implementation FIRInstanceID (Private) + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.tokenManager.authService checkinPreferences]; +} + +// This method just wraps our pre-configured auth service to make the request. +// This method is only needed by first-party users, like Remote Config. +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler { + [self.tokenManager.authService fetchCheckinInfoWithHandler:handler]; +} + +- (NSString *)appInstanceID:(NSError **)error { + return [self.keyPairStore appIdentityWithError:error]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m new file mode 100644 index 0000000..e5b39e3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m @@ -0,0 +1,1186 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import +#import +#import +#import +#import +#import +#import "FIRInstanceID+Private.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCombinedHandler.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPairStore.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenManager.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +// Public constants +NSString *const kFIRInstanceIDScopeFirebaseMessaging = @"fcm"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName kFIRInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +#else +NSString *const kFIRInstanceIDTokenRefreshNotification = @"com.firebase.iid.notif.refresh-token"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRInstanceIDInvalidNilHandlerError = @"Invalid nil handler."; + +// Private constants +int64_t const kMaxRetryIntervalForDefaultTokenInSeconds = 20 * 60; // 20 minutes +int64_t const kMinRetryIntervalForDefaultTokenInSeconds = 10; // 10 seconds +// we retry only a max 5 times. +// TODO(chliangGoogle): If we still fail we should listen for the network change notification +// since GCM would have started Reachability. We only start retrying after we see a configuration +// change. +NSInteger const kMaxRetryCountForDefaultToken = 5; + +static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment"; +static NSString *const kAPSEnvironmentDevelopmentValue = @"development"; +/// FIRMessaging selector that returns the current FIRMessaging auto init +/// enabled flag. +static NSString *const kFIRInstanceIDFCMSelectorAutoInitEnabled = @"isAutoInitEnabled"; +static NSString *const kFIRInstanceIDFCMSelectorInstance = @"messaging"; + +static NSString *const kFIRInstanceIDAPNSTokenType = @"APNSTokenType"; +static NSString *const kFIRIIDAppReadyToConfigureSDKNotification = + @"FIRAppReadyToConfigureSDKNotification"; +static NSString *const kFIRIIDAppNameKey = @"FIRAppNameKey"; +static NSString *const kFIRIIDErrorDomain = @"com.firebase.instanceid"; +static NSString *const kFIRIIDServiceInstanceID = @"InstanceID"; + +static NSInteger const kFIRIIDErrorCodeInstanceIDFailed = -121; + +typedef void (^FIRInstanceIDKeyPairHandler)(FIRInstanceIDKeyPair *keyPair, NSError *error); + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * InstanceID will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * This must match FIRMessagingAPNSTokenType in FIRMessaging.h + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) { + /// Unknown token type. + FIRInstanceIDAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRInstanceIDAPNSTokenTypeSandbox, + /// Production token type. + FIRInstanceIDAPNSTokenTypeProd, +} NS_SWIFT_NAME(InstanceIDAPNSTokenType); + +@interface FIRInstanceIDResult () +@property(nonatomic, readwrite, copy) NSString *instanceID; +@property(nonatomic, readwrite, copy) NSString *token; +@end + +@interface FIRInstanceID () + +// FIRApp configuration objects. +@property(nonatomic, readwrite, copy) NSString *fcmSenderID; +@property(nonatomic, readwrite, copy) NSString *firebaseAppID; + +// Raw APNS token data +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; + +@property(nonatomic, readwrite) FIRInstanceIDAPNSTokenType apnsTokenType; +// String-based, internal representation of APNS token +@property(nonatomic, readwrite, copy) NSString *APNSTupleString; +// Token fetched from the server automatically for the default app. +@property(nonatomic, readwrite, copy) NSString *defaultFCMToken; + +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPairStore *keyPairStore; + +// backoff and retry for default token +@property(nonatomic, readwrite, assign) NSInteger retryCountForDefaultToken; +@property(atomic, strong, nullable) + FIRInstanceIDCombinedHandler *defaultTokenFetchHandler; + +@end + +// InstanceID doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRInstanceIDInstanceProvider +@end + +@interface FIRInstanceID () +@end + +@implementation FIRInstanceIDResult +- (id)copyWithZone:(NSZone *)zone { + FIRInstanceIDResult *result = [[[self class] allocWithZone:zone] init]; + result.instanceID = self.instanceID; + result.token = self.token; + return result; +} +@end + +@implementation FIRInstanceID + +// File static to support InstanceID tests that call [FIRInstanceID instanceID] after +// [FIRInstanceID instanceIDForTests]. +static FIRInstanceID *gInstanceID; + ++ (instancetype)instanceID { + // If the static instance was created, return it. This should only be set in tests and we should + // eventually use proper dependency injection for a better test structure. + if (gInstanceID != nil) { + return gInstanceID; + } + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + FIRInstanceID *instanceID = + (FIRInstanceID *)FIR_COMPONENT(FIRInstanceIDInstanceProvider, defaultApp.container); + return instanceID; +} + +- (instancetype)initPrivately { + self = [super init]; + if (self != nil) { + // Use automatic detection of sandbox, unless otherwise set by developer + _apnsTokenType = FIRInstanceIDAPNSTokenTypeUnknown; + } + return self; +} + ++ (FIRInstanceID *)instanceIDForTests { + gInstanceID = [[FIRInstanceID alloc] initPrivately]; + [gInstanceID start]; + return gInstanceID; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Tokens + +- (NSString *)token { + if (!self.fcmSenderID.length) { + return nil; + } + + NSString *cachedToken = [self cachedTokenIfAvailable]; + + if (cachedToken) { + return cachedToken; + } else { + // If we've never had a cached default token, we should fetch one because unrelatedly, + // this request will help us determine whether the locally-generated Instance ID keypair is not + // unique, and therefore generate a new one. + [self defaultTokenWithHandler:nil]; + return nil; + } +} + +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler { + FIRInstanceID_WEAKIFY(self); + [self getIDWithHandler:^(NSString *identity, NSError *error) { + FIRInstanceID_STRONGIFY(self); + // This is in main queue already + if (error) { + if (handler) { + handler(nil, error); + } + return; + } + FIRInstanceIDResult *result = [[FIRInstanceIDResult alloc] init]; + result.instanceID = identity; + NSString *cachedToken = [self cachedTokenIfAvailable]; + if (cachedToken) { + if (handler) { + result.token = cachedToken; + handler(result, nil); + } + // If no handler, simply return since client has generated iid and token. + return; + } + [self defaultTokenWithHandler:^(NSString *_Nullable token, NSError *_Nullable error) { + if (handler) { + if (error) { + handler(nil, error); + return; + } + result.token = token; + handler(result, nil); + } + }]; + }]; +} + +- (NSString *)cachedTokenIfAvailable { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope]; + return cachedTokenInfo.token; +} + +- (void)setDefaultFCMToken:(NSString *)defaultFCMToken { + if (_defaultFCMToken && defaultFCMToken && [defaultFCMToken isEqualToString:_defaultFCMToken]) { + return; + } + + _defaultFCMToken = defaultFCMToken; + + // Sending this notification out will ensure that FIRMessaging has the updated + // default FCM token. + NSNotification *internalDefaultTokenNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenNotification + object:_defaultFCMToken]; + [[NSNotificationQueue defaultQueue] enqueueNotification:internalDefaultTokenNotification + postingStyle:NSPostASAP]; +} + +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + _FIRInstanceIDDevAssert(handler != nil && [authorizedEntity length] && [scope length], + @"Invalid authorizedEntity or scope to new token"); + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID000, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + NSMutableDictionary *tokenOptions = [NSMutableDictionary dictionary]; + if (options.count) { + [tokenOptions addEntriesFromDictionary:options]; + } + + NSString *APNSKey = kFIRInstanceIDTokenOptionsAPNSKey; + NSString *serverTypeKey = kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + + if (tokenOptions[APNSKey] != nil && tokenOptions[serverTypeKey] == nil) { + // APNS key was given, but server type is missing. Supply the server type with automatic + // checking. This can happen when the token is requested from FCM, which does not include a + // server type during its request. + tokenOptions[serverTypeKey] = @([self isSandboxApp]); + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + if (FIRInstanceIDIsValidGCMScope(scope) && !tokenOptions[APNSKey]) { + errorCode = kFIRInstanceIDErrorCodeMissingAPNSToken; + } else if (FIRInstanceIDIsValidGCMScope(scope) && + ![tokenOptions[APNSKey] isKindOfClass:[NSData class]]) { + errorCode = kFIRInstanceIDErrorCodeInvalidRequest; + } else if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.keyPairStore) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDTokenHandler newHandler = ^(NSString *token, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(token, error); + }); + }; + + if (errorCode != noError) { + newHandler(nil, [NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + // TODO(chliangGoogle): Add some validation logic that the APNs token data and sandbox value are + // supplied in the valid format (NSData and BOOL, respectively). + + // Add internal options + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(nil, error); + return; + } + + // Only use the token in the cache if the APNSInfo matches what the request's options has. + // It's possible for the request to be with a newer APNs device token, which should be + // honored. + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; + if (cachedTokenInfo) { + // Ensure that the cached token matches APNs data before returning it. + FIRInstanceIDAPNSInfo *optionsAPNSInfo = + [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions]; + // If either the APNs info is missing in both, or if they are an exact match, then we can + // use this cached token. + if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) || + [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) { + newHandler(cachedTokenInfo.token, nil); + return; + } + } + + FIRInstanceID_WEAKIFY(self); + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(nil, newError); + + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:[authorizedEntity copy] + scope:[scope copy] + keyPair:keyPair + options:tokenOptions + handler:newHandler]; + } + }]; + }]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler { + _FIRInstanceIDDevAssert(handler != nil && [authorizedEntity length] && [scope length], + @"Invalid authorizedEntity or scope to delete token"); + + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID001, + kFIRInstanceIDInvalidNilHandlerError); + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + + if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.keyPairStore) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) { + // If a default token is deleted successfully, reset the defaultFCMToken too. + if (!error && [authorizedEntity isEqualToString:self.fcmSenderID] && + [scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + self.defaultFCMToken = nil; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (errorCode != noError) { + newHandler([NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(newError); + + } else { + [self.tokenManager deleteTokenWithAuthorizedEntity:authorizedEntity + scope:scope + keyPair:keyPair + handler:newHandler]; + } + }]; + }]; +} + +- (void)asyncLoadKeyPairWithHandler:(FIRInstanceIDKeyPairHandler)handler { + FIRInstanceID_WEAKIFY(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + FIRInstanceID_STRONGIFY(self); + + NSError *error = nil; + FIRInstanceIDKeyPair *keyPair = [self.keyPairStore loadKeyPairWithError:&error]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID002, + @"Failed to retreieve keyPair %@", error); + if (handler) { + handler(nil, error); + } + } else if (!keyPair && !error) { + if (handler) { + handler(nil, + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]); + } + } else { + if (handler) { + handler(keyPair, nil); + } + } + }); + }); +} + +#pragma mark - Identity + +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler { + _FIRInstanceIDDevAssert(handler, @"Invalid nil handler to getIdentity"); + + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID003, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSString *, NSError *) = ^(NSString *identity, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(identity, error); + }); + }; + + if (!self.keyPairStore) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidStart]; + callHandlerOnMainThread(nil, error); + return; + } + + FIRInstanceID_WEAKIFY(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + FIRInstanceID_STRONGIFY(self); + NSError *error; + NSString *appIdentity = [self.keyPairStore appIdentityWithError:&error]; + // When getID is explicitly called, trigger getToken to make sure token always exists. + // This is to avoid ID conflict (ID is not checked for conflict until we generate a token) + if (appIdentity) { + [self token]; + } + callHandlerOnMainThread(appIdentity, error); + }); +} + +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler { + _FIRInstanceIDDevAssert(handler, @"Invalid nil handler to delete Identity"); + + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID004, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSError *) = ^(NSError *error) { + if ([NSThread isMainThread]) { + handler(error); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (!self.keyPairStore) { + FIRInstanceIDErrorCode error = kFIRInstanceIDErrorCodeInvalidStart; + callHandlerOnMainThread([NSError errorWithFIRInstanceIDErrorCode:error]); + return; + } + + FIRInstanceID_WEAKIFY(self); + void (^deleteTokensHandler)(NSError *) = ^void(NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + callHandlerOnMainThread(error); + return; + } + [self deleteIdentityWithHandler:^(NSError *error) { + callHandlerOnMainThread(error); + }]; + }; + + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + callHandlerOnMainThread(newError); + } else { + [self.tokenManager deleteAllTokensWithKeyPair:keyPair handler:deleteTokensHandler]; + } + }]; +} + +- (void)notifyIdentityReset { + [self deleteIdentityWithHandler:nil]; +} + +// Delete all the local cache checkin, IID and token. +- (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler { + // Delete tokens. + [self.tokenManager deleteAllTokensLocallyWithHandler:^(NSError *deleteTokenError) { + // Reset FCM token. + self.defaultFCMToken = nil; + if (deleteTokenError) { + if (handler) { + handler(deleteTokenError); + } + return; + } + + // Delete Instance ID. + [self.keyPairStore + deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType + handler:^(NSError *error) { + NSError *deletePlistError; + [self.keyPairStore + removeKeyPairCreationTimePlistWithError:&deletePlistError]; + if (error || deletePlistError) { + if (handler) { + // Prefer to use the delete Instance ID error. + error = [NSError + errorWithFIRInstanceIDErrorCode: + kFIRInstanceIDErrorCodeUnknown + userInfo:@{ + NSUnderlyingErrorKey : error + ? error + : deletePlistError + }]; + handler(error); + } + return; + } + // Delete checkin. + [self.tokenManager.authService + resetCheckinWithHandler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + // Only request new token if FCM auto initialization is + // enabled. + if ([self isFCMAutoInitEnabled]) { + // Deletion succeeds! Requesting new checkin, IID and token. + // TODO(chliangGoogle) see if dispatch_after is necessary + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(0.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self defaultTokenWithHandler:nil]; + }); + } + if (handler) { + handler(nil); + } + }]; + }]; + }]; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-iid" + withVersion:FIRInstanceIDCurrentLibraryVersion()]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // Ensure it's cached so it returns the same instance every time instanceID is called. + *isCacheable = YES; + FIRInstanceID *instanceID = [[FIRInstanceID alloc] initPrivately]; + [instanceID start]; + return instanceID; + }; + FIRComponent *instanceIDProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstanceIDInstanceProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; + return @[ instanceIDProvider ]; +} + ++ (void)configureWithApp:(FIRApp *)app { + if (!app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeFIRApp002, + @"Firebase Instance ID only works with the default app."); + return; + } + [[FIRInstanceID instanceID] configureInstanceIDWithOptions:app.options app:app]; +} + +- (void)configureInstanceIDWithOptions:(FIROptions *)options app:(FIRApp *)firApp { + NSString *GCMSenderID = options.GCMSenderID; + if (!GCMSenderID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeFIRApp000, + @"Firebase not set up correctly, nil or empty senderID."); + [FIRInstanceID exitWithReason:@"GCM_SENDER_ID must not be nil or empty." forFirebaseApp:firApp]; + return; + } + + self.fcmSenderID = GCMSenderID; + self.firebaseAppID = firApp.options.googleAppID; + + // FCM generates a FCM token during app start for sending push notification to device. + // This is not needed for app extension. + if (![GULAppEnvironmentUtil isAppExtension]) { + [self didCompleteConfigure]; + } +} + ++ (NSError *)configureErrorWithReason:(nonnull NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", kFIRIIDServiceInstanceID]; + if (!reason.length) { + reason = @"Unknown reason"; + } + + NSDictionary *userInfo = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + + return [NSError errorWithDomain:kFIRIIDErrorDomain + code:kFIRIIDErrorCodeInstanceIDFailed + userInfo:userInfo]; +} + +// If the firebaseApp is available we should send logs for the error through it before +// raising an exception. ++ (void)exitWithReason:(nonnull NSString *)reason forFirebaseApp:(FIRApp *)firebaseApp { + [firebaseApp sendLogsWithServiceName:kFIRIIDServiceInstanceID + version:FIRInstanceIDCurrentLibraryVersion() + error:[self configureErrorWithReason:reason]]; + + [NSException raise:kFIRIIDErrorDomain + format:@"Could not configure Firebase InstanceID. %@", reason]; +} + +// This is used to start any operations when we receive FirebaseSDK setup notification +// from FIRCore. +- (void)didCompleteConfigure { + NSString *cachedToken = [self cachedTokenIfAvailable]; + // When there is a cached token, do the token refresh. + if (cachedToken) { + // Clean up expired tokens by checking the token refresh policy. + if ([self.tokenManager checkForTokenRefreshPolicy]) { + // Default token is expired, fetch default token from server. + [self defaultTokenWithHandler:nil]; + } + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } else if ([self isFCMAutoInitEnabled]) { + // When there is no cached token, must check auto init is enabled. + // If it's disabled, don't initiate token generation/refresh. + // If no cache token and auto init is enabled, fetch a token from server. + [self defaultTokenWithHandler:nil]; + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } + // ONLY checkin when auto data collection is turned on. + if ([self isFCMAutoInitEnabled]) { + [self.tokenManager.authService scheduleCheckin:YES]; + } +} + +- (BOOL)isFCMAutoInitEnabled { + Class messagingClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + // Firebase Messaging is not installed, auto init should be disabled since it's for FCM. + if (!messagingClass) { + return NO; + } + + // Messaging doesn't have the singleton method, auto init should be enabled since FCM exists. + SEL instanceSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorInstance); + if (![messagingClass respondsToSelector:instanceSelector]) { + return YES; + } + + // Get FIRMessaging shared instance. + IMP messagingInstanceIMP = [messagingClass methodForSelector:instanceSelector]; + id (*getMessagingInstance)(id, SEL) = (void *)messagingInstanceIMP; + id messagingInstance = getMessagingInstance(messagingClass, instanceSelector); + + // Messaging doesn't have the property, auto init should be enabled since FCM exists. + SEL autoInitSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorAutoInitEnabled); + if (![messagingInstance respondsToSelector:autoInitSelector]) { + return YES; + } + + // Get autoInitEnabled method. + IMP isAutoInitEnabledIMP = [messagingInstance methodForSelector:autoInitSelector]; + BOOL (*isAutoInitEnabled)(id, SEL) = (BOOL(*)(id, SEL))isAutoInitEnabledIMP; + + // Check FCM's isAutoInitEnabled property. + return isAutoInitEnabled(messagingInstance, autoInitSelector); +} + +// Actually makes InstanceID instantiate both the IID and Token-related subsystems. +- (void)start { + if (![FIRInstanceIDStore hasSubDirectory:kFIRInstanceIDSubDirectoryName]) { + [FIRInstanceIDStore createSubDirectory:kFIRInstanceIDSubDirectoryName]; + } + + [self setupTokenManager]; + [self setupKeyPairManager]; + [self setupNotificationListeners]; +} + +// Creates the token manager, which is used for fetching, caching, and retrieving tokens. +- (void)setupTokenManager { + self.tokenManager = [[FIRInstanceIDTokenManager alloc] init]; +} + +// Creates a key pair manager, which stores the public/private keys needed to generate an +// application instance ID. +- (void)setupKeyPairManager { + self.keyPairStore = [[FIRInstanceIDKeyPairStore alloc] init]; + if ([self.keyPairStore invalidateKeyPairsIfNeeded]) { + // Reset tokens right away when keypair is deleted, otherwise async call can make first query + // of token happens before reset old tokens during app start. + // TODO(chliangGoogle): Delete all tokens on server too, using + // deleteAllTokensWithKeyPair:handler:. This requires actually retrieving the invalid keypair + // from Keychain, which is something that the key pair store does not currently do. + [self.tokenManager deleteAllTokensLocallyWithHandler:nil]; + } +} + +- (void)setupNotificationListeners { + // To prevent double notifications remove observer from all events during setup. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + [center addObserver:self + selector:@selector(notifyIdentityReset) + name:kFIRInstanceIDIdentityInvalidatedNotification + object:nil]; + [center addObserver:self + selector:@selector(notifyAPNSTokenIsSet:) + name:kFIRInstanceIDAPNSTokenNotification + object:nil]; +} + +#pragma mark - Private Helpers +/// Maximum retry count to fetch the default token. ++ (int64_t)maxRetryCountForDefaultToken { + return kMaxRetryCountForDefaultToken; +} + +/// Minimum interval in seconds between retries to fetch the default token. ++ (int64_t)minIntervalForDefaultTokenRetry { + return kMinRetryIntervalForDefaultTokenInSeconds; +} + +/// Maximum retry interval between retries to fetch default token. ++ (int64_t)maxRetryIntervalForDefaultTokenInSeconds { + return kMaxRetryIntervalForDefaultTokenInSeconds; +} + +- (NSInteger)retryIntervalToFetchDefaultToken { + if (self.retryCountForDefaultToken >= [[self class] maxRetryCountForDefaultToken]) { + return (NSInteger)[[self class] maxRetryIntervalForDefaultTokenInSeconds]; + } + // exponential backoff with a fixed initial retry time + // 11s, 22s, 44s, 88s ... + int64_t minInterval = [[self class] minIntervalForDefaultTokenRetry]; + return (NSInteger)MIN( + (1 << self.retryCountForDefaultToken) + minInterval * self.retryCountForDefaultToken, + kMaxRetryIntervalForDefaultTokenInSeconds); +} + +- (void)defaultTokenWithHandler:(nullable FIRInstanceIDTokenHandler)aHandler { + [self defaultTokenWithRetry:NO handler:aHandler]; +} + +/** + * @param retry Indicates if the method is called to perform a retry after a failed attempt. + * If `YES`, then actual token request will be performed even if `self.defaultTokenFetchHandler != + * nil` + */ +- (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHandler)aHandler { + BOOL shouldPerformRequest = retry || self.defaultTokenFetchHandler == nil; + + if (!self.defaultTokenFetchHandler) { + self.defaultTokenFetchHandler = [[FIRInstanceIDCombinedHandler alloc] init]; + } + + if (aHandler) { + [self.defaultTokenFetchHandler addHandler:aHandler]; + } + + if (!shouldPerformRequest) { + return; + } + + NSDictionary *instanceIDOptions = @{}; + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging && self.apnsTokenData) { + BOOL isSandboxApp = (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + instanceIDOptions = @{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp), + }; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenHandler newHandler = ^void(NSString *token, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID009, + @"Failed to fetch default token %@", error); + + // This notification can be sent multiple times since we can't guarantee success at any point + // of time. + NSNotification *tokenFetchFailNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenFailNotification + object:[error copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenFetchFailNotification + postingStyle:NSPostASAP]; + + self.retryCountForDefaultToken = (NSInteger)MIN(self.retryCountForDefaultToken + 1, + [[self class] maxRetryCountForDefaultToken]); + + // Do not retry beyond the maximum limit. + if (self.retryCountForDefaultToken < [[self class] maxRetryCountForDefaultToken]) { + NSInteger retryInterval = [self retryIntervalToFetchDefaultToken]; + [self retryGetDefaultTokenAfter:retryInterval]; + } else { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID007, + @"Failed to retrieve the default FCM token after %ld retries", + (long)self.retryCountForDefaultToken); + [self performDefaultTokenHandlerWithToken:nil error:error]; + } + } else { + // If somebody updated IID with APNS token while our initial request did not have it + // set we need to update it on the server. + NSData *deviceTokenInRequest = instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSKey]; + BOOL isSandboxInRequest = + [instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey] boolValue]; + // Note that APNSTupleStringInRequest will be nil if deviceTokenInRequest is nil + NSString *APNSTupleStringInRequest = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + deviceTokenInRequest, isSandboxInRequest); + // If the APNs value either remained nil, or was the same non-nil value, the APNs value + // did not change. + BOOL APNSRemainedSameDuringFetch = + (self.APNSTupleString == nil && APNSTupleStringInRequest == nil) || + ([self.APNSTupleString isEqualToString:APNSTupleStringInRequest]); + if (!APNSRemainedSameDuringFetch && hasFirebaseMessaging) { + // APNs value did change mid-fetch, so the token should be re-fetched with the current APNs + // value. + [self retryGetDefaultTokenAfter:0]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeRefetchingTokenForAPNS, + @"Received APNS token while fetching default token. " + @"Refetching default token."); + // Do not notify and handle completion handler since this is a retry. + // Simply return. + return; + } else { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeInstanceID010, + @"Successfully fetched default token."); + } + // Post the required notifications if somebody is waiting. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@", + token); + NSString *previousFCMToken = self.defaultFCMToken; + self.defaultFCMToken = token; + + // Only notify of token refresh if we have a new valid token that's different than before + if (self.defaultFCMToken.length && ![self.defaultFCMToken isEqualToString:previousFCMToken]) { + NSNotification *tokenRefreshNotification = + [NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification + object:[self.defaultFCMToken copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification + postingStyle:NSPostASAP]; + + [self performDefaultTokenHandlerWithToken:token error:nil]; + } + } + }; + + [self tokenWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope + options:instanceIDOptions + handler:newHandler]; +} + +/** + * + */ +- (void)performDefaultTokenHandlerWithToken:(NSString *)token error:(NSError *)error { + if (!self.defaultTokenFetchHandler) { + return; + } + + [self.defaultTokenFetchHandler combinedHandler](token, error); + self.defaultTokenFetchHandler = nil; +} + +- (void)retryGetDefaultTokenAfter:(NSTimeInterval)retryInterval { + FIRInstanceID_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + // Pass nil: no new handlers to be added, currently existing handlers + // will be called + [self defaultTokenWithRetry:YES handler:nil]; + }); +} + +#pragma mark - APNS Token +// This should only be triggered from FCM. +- (void)notifyAPNSTokenIsSet:(NSNotification *)notification { + NSData *token = notification.object; + if (!token || ![token isKindOfClass:[NSData class]]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal002, @"Invalid APNS token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSInteger type = [notification.userInfo[kFIRInstanceIDAPNSTokenType] integerValue]; + + // The APNS token is being added, or has changed (rare) + if ([self.apnsTokenData isEqualToData:token]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID011, + @"Trying to reset APNS token to the same value. Will return"); + return; + } + // Use this token type for when we have to automatically fetch tokens in the future + self.apnsTokenType = type; + BOOL isSandboxApp = (type == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + self.apnsTokenData = [token copy]; + self.APNSTupleString = FIRInstanceIDAPNSTupleStringForTokenAndServerType(token, isSandboxApp); + + // Pro-actively invalidate the default token, if the APNs change makes it + // invalid. Previously, we invalidated just before fetching the token. + NSArray *invalidatedTokens = + [self.tokenManager updateTokensToAPNSDeviceToken:self.apnsTokenData isSandbox:isSandboxApp]; + + // Re-fetch any invalidated tokens automatically, this time with the current APNs token, so that + // they are up-to-date. + if (invalidatedTokens.count > 0) { + FIRInstanceID_WEAKIFY(self); + [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + NSMutableDictionary *tokenOptions = [@{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp) + } mutableCopy]; + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + for (FIRInstanceIDTokenInfo *tokenInfo in invalidatedTokens) { + if ([tokenInfo.token isEqualToString:self.defaultFCMToken]) { + // We will perform a special fetch for the default FCM token, so that the delegate methods + // are called. For all others, we will do an internal re-fetch. + [self defaultTokenWithHandler:nil]; + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope + keyPair:keyPair + options:tokenOptions + handler:^(NSString *_Nullable token, + NSError *_Nullable error){ + + }]; + } + } + }]; + } +} + +- (BOOL)isSandboxApp { + static BOOL isSandboxApp = YES; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + isSandboxApp = ![self isProductionApp]; + }); + return isSandboxApp; +} + +- (BOOL)isProductionApp { + const BOOL defaultAppTypeProd = YES; + + NSError *error = nil; + + Class envClass = NSClassFromString(@"FIRAppEnvironmentUtil"); + SEL isSimulatorSelector = NSSelectorFromString(@"isSimulator"); + if ([envClass respondsToSelector:isSimulatorSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([envClass performSelector:isSimulatorSelector]) { +#pragma clang diagnostic pop + [self logAPNSConfigurationError:@"Running InstanceID on a simulator doesn't have APNS. " + @"Use prod profile by default."]; + return defaultAppTypeProd; + } + } + + NSString *path = [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent:@"embedded.mobileprovision"]; + + // Apps distributed via AppStore or TestFlight use the Production APNS certificates. + SEL isFromAppStoreSelector = NSSelectorFromString(@"isFromAppStore"); + if ([envClass respondsToSelector:isFromAppStoreSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([envClass performSelector:isFromAppStoreSelector]) { +#pragma clang diagnostic pop + return defaultAppTypeProd; + } + } + + SEL isAppStoreReceiptSandboxSelector = NSSelectorFromString(@"isAppStoreReceiptSandbox"); + if ([envClass respondsToSelector:isAppStoreReceiptSandboxSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([envClass performSelector:isAppStoreReceiptSandboxSelector] && !path.length) { +#pragma clang diagnostic pop + // Distributed via TestFlight + return defaultAppTypeProd; + } + } + + NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error]; + + if (!profileData.length || error) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the + // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit + // ASCII. Replace any 0s or invalid characters in the input. + uint8_t *profileBytes = (uint8_t *)profileData.bytes; + for (int i = 0; i < profileData.length; i++) { + uint8_t currentByte = profileBytes[i]; + if (!currentByte || currentByte > 127) { + profileBytes[i] = '.'; + } + } + + NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes + length:profileData.length + encoding:NSASCIIStringEncoding + freeWhenDone:NO]; + + if (error || !embeddedProfile.length) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; + NSString *plistContents; + if ([scanner scanUpToString:@"" intoString:&plistContents]) { + plistContents = [plistContents stringByAppendingString:@""]; + } + } + + if (!plistContents.length) { + return defaultAppTypeProd; + } + + NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; + if (!data.length) { + [self logAPNSConfigurationError:@"Couldn't read plist fetched from embedded mobileprovision"]; + return defaultAppTypeProd; + } + + NSError *plistMapError; + id plistData = [NSPropertyListSerialization propertyListWithData:data + options:NSPropertyListImmutable + format:nil + error:&plistMapError]; + if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { + NSString *errorString = + [NSString stringWithFormat:@"Error while converting assumed plist to dict %@", + plistMapError.localizedDescription]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + NSDictionary *plistMap = (NSDictionary *)plistData; + + if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID012, + @"Provisioning profile has specifically provisioned devices, " + @"most likely a Dev profile."); + } + + NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey]; + NSString *debugString __unused = + [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID013, @"%@", debugString); + + // No aps-environment in the profile. + if (!apsEnvironment.length) { + [self logAPNSConfigurationError:@"No aps-environment set. If testing on a device APNS is not " + @"correctly configured. Please recheck your provisioning " + @"profiles. If testing on a simulator this is fine since APNS " + @"doesn't work on the simulator."]; + return defaultAppTypeProd; + } + + if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) { + return NO; + } + + return defaultAppTypeProd; +} + +/// Log error messages only when Messaging exists in the pod. +- (void)logAPNSConfigurationError:(NSString *)errorString { + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID014, @"%@", errorString); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID015, @"%@", errorString); + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h new file mode 100644 index 0000000..92b2469 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an APNS device token and whether its environment is for sandbox. + * It can read from and write to an NSDictionary for simple serialization. + */ +@interface FIRInstanceIDAPNSInfo : NSObject + +/// The APNs device token, provided by the OS to the application delegate +@property(nonatomic, readonly, strong) NSData *deviceToken; +/// Represents whether or not this is deviceToken is for the sandbox +/// environment, or production. +@property(nonatomic, readonly, getter=isSandbox) BOOL sandbox; + +/** + * Initializes the receiver with an APNs device token, and boolean + * representing whether that token is for the sandbox environment. + * + * @param deviceToken The APNs device token typically provided by the + * operating system. + * @param isSandbox YES if the APNs device token is for the sandbox + * environment, or NO if it is for production. + * @return An instance of FIRInstanceIDAPNSInfo. + */ +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox; + +/** + * Initializes the receiver from a token options dictionary containing data + * within the `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey` keys. The token should be an + * NSData blob, and the sandbox value should be an NSNumber + * representing a boolean value. + * + * @param dictionary A dictionary containing values under the keys + * `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey`. + * @return An instance of FIRInstanceIDAPNSInfo, or nil if the + * dictionary data was invalid or missing. + */ +- (nullable instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary; + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m new file mode 100644 index 0000000..d1f9d08 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAPNSInfo.h" + +#import "FIRInstanceIDConstants.h" + +/// The key used to find the APNs device token in an archive. +NSString *const kFIRInstanceIDAPNSInfoTokenKey = @"device_token"; +/// The key used to find the sandbox value in an archive. +NSString *const kFIRInstanceIDAPNSInfoSandboxKey = @"sandbox"; + +@implementation FIRInstanceIDAPNSInfo + +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox { + self = [super init]; + if (self) { + _deviceToken = [deviceToken copy]; + _sandbox = isSandbox; + } + return self; +} + +- (instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary { + id deviceToken = dictionary[kFIRInstanceIDTokenOptionsAPNSKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + + id isSandbox = dictionary[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if (![isSandbox isKindOfClass:[NSNumber class]]) { + return nil; + } + self = [super init]; + if (self) { + _deviceToken = (NSData *)deviceToken; + _sandbox = ((NSNumber *)isSandbox).boolValue; + } + return self; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey]; + return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.deviceToken forKey:kFIRInstanceIDAPNSInfoTokenKey]; + [aCoder encodeBool:self.sandbox forKey:kFIRInstanceIDAPNSInfoSandboxKey]; +} + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo { + if ([super isEqual:otherInfo]) { + return YES; + } + return ([self.deviceToken isEqualToData:otherInfo.deviceToken] && + self.isSandbox == otherInfo.isSandbox); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h new file mode 100644 index 0000000..347ddda --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h @@ -0,0 +1,98 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *__nonnull const kFIRInstanceIDKeychainWildcardIdentifier; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper around storing FCM auth data in iOS keychain. + */ +@interface FIRInstanceIDAuthKeychain : NSObject + +/** + * Designated Initializer. Init a generic `SecClassGenericPassword` keychain with `identifier` + * as the `kSecAttrGeneric`. + * + * @param identifier The generic attribute to be used by the keychain. + * + * @return A Keychain object with `kSecAttrGeneric` attribute set to identifier. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier; + +/** + * Get keychain items matching the given service and account. The service and/or account + * can be a wildcard (`kFIRInstanceIDKeychainWildcardIdentifier`), which case the query + * will include all items matching any services and/or accounts. + * + * @param service The kSecAttrService used to save the password. Can be wildcard. + * @param account The kSecAttrAccount used to save the password. Can be wildcard. + * + * @return An array of |NSData|s matching the provided inputs. + */ +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account; + +/** + * Get keychain item for a given service and account. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * + * @return A cached keychain item for a given account and service, or nil if it was not + * found or could not be retrieved. + */ +- (NSData *)dataForService:(NSString *)service account:(NSString *)account; + +/** + * Remove the cached items from the keychain matching the service, account and access group. + * In case the items do not exist, YES is returned but with a valid error object with code + * `errSecItemNotFound`. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * @param handler The callback handler which is invoked when the remove operation is complete, with + * an error if there is any. + */ +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *error))handler; + +/** + * Set the data for a given service and account with a specific accessibility. If + * accessibility is NULL we use `kSecAttrAccessibleAlwaysThisDeviceOnly` which + * prevents backup and restore to iCloud, and works for app extension that can + * execute right after a device is restarted (and not unlocked). + * + * @param data The data to save. + * @param service The `kSecAttrService` used to save the password. + * @param accessibility The `kSecAttrAccessibility` used to save the password. If NULL + * set this to `kSecAttrAccessibleAlwaysThisDeviceOnly`. + * @param account The `kSecAttrAccount` used to save the password. + * @param handler The callback handler which is invoked when the add operation is complete, + * with an error if there is any. + * + */ +- (void)setData:(NSData *)data + forService:(NSString *)service + accessibility:(nullable CFTypeRef)accessibility + account:(NSString *)account + handler:(nullable void (^)(NSError *))handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m new file mode 100644 index 0000000..f75362f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m @@ -0,0 +1,215 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" + +/** + * The error type representing why we couldn't read data from the keychain. + */ +typedef NS_ENUM(int, FIRInstanceIDKeychainErrorType) { + kFIRInstanceIDKeychainErrorBadArguments = -1301, +}; + +NSString *const kFIRInstanceIDKeychainWildcardIdentifier = @"*"; + +@interface FIRInstanceIDAuthKeychain () + +@property(nonatomic, copy) NSString *generic; +// cachedKeychainData is keyed by service and account, the value is an array of NSData. +// It is used to cache the tokens per service, per account, as well as checkin data per service, +// per account inside the keychain. +@property(nonatomic) + NSMutableDictionary *> *> + *cachedKeychainData; + +@end + +@implementation FIRInstanceIDAuthKeychain + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + _generic = [identifier copy]; + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } + return self; +} + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service + account:(NSString *)account + generic:(NSString *)generic { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + if ([generic length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:generic]) { + finalQuery[(__bridge NSString *)kSecAttrGeneric] = generic; + } + if ([account length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:account]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + if ([service length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:service]) { + finalQuery[(__bridge NSString *)kSecAttrService] = service; + } + return finalQuery; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account generic:self.generic]; +} + +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account { + // If query wildcard service, it asks for all the results, which always query from keychain. + if (![service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + ![account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + _cachedKeychainData[service][account]) { + // As long as service, account array exist, even it's empty, it means we've queried it before, + // returns the cache value. + return _cachedKeychainData[service][account]; + } + + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + + NSMutableArray *results; + keychainQuery[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + // FIRInstanceIDKeychain should only take a query and return a result, will handle the query here. + NSArray *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); + + if (!passwordInfos) { + // Nothing was found, simply return from this sync block. + // Make sure to label the cache entry empty, signaling that we've queried this entry. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return @[]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + return @[]; + } + NSInteger numPasswords = passwordInfos.count; + results = [[NSMutableArray alloc] init]; + for (NSUInteger i = 0; i < numPasswords; i++) { + NSDictionary *passwordInfo = [passwordInfos objectAtIndex:i]; + if (passwordInfo[(__bridge id)kSecValueData]) { + [results addObject:passwordInfo[(__bridge id)kSecValueData]]; + } + } + + // We query the keychain because it didn't exist in cache, now query is done, update the result in + // the cache. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return [results copy]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:[results copy] forKey:account]; + } else { + NSMutableDictionary *entry = [@{account : [results copy]} mutableCopy]; + [_cachedKeychainData setObject:entry forKey:service]; + } + return [results copy]; +} + +- (NSData *)dataForService:(NSString *)service account:(NSString *)account { + NSArray *items = [self itemsMatchingService:service account:account]; + // If items is nil or empty, nil will be returned. + return items.firstObject; +} + +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *error))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all keychain items. + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } else if ([account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all entries under service, + if (_cachedKeychainData[service]) { + _cachedKeychainData[service] = [[NSMutableDictionary alloc] init]; + } + } else if (_cachedKeychainData[service]) { + // We should keep the service/account entry instead of nil so we know + // it's "empty entry" instead of "not query from keychain yet". + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:keychainQuery handler:handler]; +} + +- (void)setData:(NSData *)data + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + handler:(void (^)(NSError *))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + if (handler) { + handler([NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:kFIRInstanceIDKeychainErrorBadArguments + userInfo:nil]); + } + return; + } + [self removeItemsMatchingService:service + account:account + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (data.length > 0) { + NSMutableDictionary *keychainQuery = + [self keychainQueryForService:service account:account]; + keychainQuery[(__bridge id)kSecValueData] = data; + + if (accessibility != NULL) { + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)accessibility; + } else { + // Defaults to No backup + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly; + } + [[FIRInstanceIDKeychain sharedInstance] + addItemWithQuery:keychainQuery + handler:handler]; + } + }]; + // Set the cache value. This must happen after removeItemsMatchingService:account:handler was + // called, so the cache value was reset before setting a new value. + if (_cachedKeychainData[service]) { + if (_cachedKeychainData[service][account]) { + _cachedKeychainData[service][account] = @[ data ]; + } else { + [_cachedKeychainData[service] setObject:@[ data ] forKey:account]; + } + } else { + [_cachedKeychainData setObject:[@{account : @[ data ]} mutableCopy] forKey:service]; + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h new file mode 100644 index 0000000..1fb715e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "FIRInstanceIDCheckinService.h" + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDStore; + +/** + * FIRInstanceIDAuthService is responsible for retrieving, caching, and supplying checkin info + * for the rest of Instance ID. A checkin can be scheduled, meaning that it will keep retrying the + * checkin request until it is successful. A checkin can also be requested directly, with a + * completion handler. + */ +@interface FIRInstanceIDAuthService : NSObject + +/** + * Used only for testing. In addition to taking a store (for locally caching the checkin info), it + * also takes a checkinService. + */ +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store; + +/** + * Initializes the auth service given a store (which provides the local caching of checkin info). + * This initializer will create its own instance of FIRInstanceIDCheckinService. + */ +- (instancetype)initWithStore:(FIRInstanceIDStore *)store; + +#pragma mark - Checkin Service + +/** + * Checks if the current deviceID and secret are valid or not. + * + * @return YES if the checkin credentials are valid else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Fetch checkin info from the server. This would usually refresh the existing + * checkin credentials for the current app. + * + * @param handler The completion handler to invoke once the checkin info has been + * refreshed. + */ +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Schedule checkin. Will hit the network only if the currently loaded checkin + * preferences are stale. + * + * @param immediately YES if we want it to be scheduled immediately else NO. + */ +- (void)scheduleCheckin:(BOOL)immediately; + +/** + * Returns the checkin preferences currently loaded in memory. The Checkin preferences + * can be either valid or invalid. + * + * @return The checkin preferences loaded in memory. + */ +- (FIRInstanceIDCheckinPreferences *)checkinPreferences; + +/** + * Cancels any ongoing checkin fetch, if any. + */ +- (void)stopCheckinRequest; + +/** + * Resets the checkin information. + * + * @param handler The callback handler which is invoked when checkin reset is complete, + * with an error if there is any. + */ +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m new file mode 100644 index 0000000..8c33c44 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m @@ -0,0 +1,302 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "NSError+FIRInstanceID.h" + +// Max time interval between checkin retry in seconds. +static const int64_t kMaxCheckinRetryIntervalInSeconds = 1 << 5; + +@interface FIRInstanceIDAuthService () + +// Used to retrieve and cache the checkin info to disk and Keychain. +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *store; +// Used to perform single checkin fetches. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinService *checkinService; +// The current checkin info. It will be compared to what is retrieved to determine whether it is +// different than what is in the cache. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; + +// This array will track multiple handlers waiting for checkin to be performed. When a checkin +// request completes, all the handlers will be notified. +// Changes to the checkinHandlers array should happen in a thread-safe manner. +@property(nonatomic, readonly, strong) + NSMutableArray *checkinHandlers; + +// This is set to true if there is a checkin request in-flight. +@property(atomic, readwrite, assign) BOOL isCheckinInProgress; +// This timer is used a perform checkin retries. It is cancellable. +@property(atomic, readwrite, strong) NSTimer *scheduledCheckinTimer; +// The number of times checkin has been retried during a scheduled checkin. +@property(atomic, readwrite, assign) int checkinRetryCount; + +@end + +@implementation FIRInstanceIDAuthService + +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store { + self = [super init]; + if (self) { + _store = store; + _checkinPreferences = [_store cachedCheckinPreferences]; + _checkinService = checkinService; + _checkinHandlers = [NSMutableArray array]; + } + return self; +} + +- (void)dealloc { + [_scheduledCheckinTimer invalidate]; +} + +- (instancetype)initWithStore:(FIRInstanceIDStore *)store { + FIRInstanceIDCheckinService *checkinService = [[FIRInstanceIDCheckinService alloc] init]; + return [self initWithCheckinService:checkinService store:store]; +} + +#pragma mark - Schedule Checkin + +- (void)scheduleCheckin:(BOOL)immediately { + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + // Checkin is already scheduled, so this (non-immediate) request can be ignored. + if (!immediately && [self.scheduledCheckinTimer isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService000, + @"Checkin sync already scheduled. Will not schedule."); + return; + } + + if (immediately) { + [self performScheduledCheckin]; + } else { + int64_t checkinRetryDuration = [self calculateNextCheckinRetryIntervalInSeconds]; + [self startCheckinTimerWithDuration:(NSTimeInterval)checkinRetryDuration]; + } +} + +- (void)startCheckinTimerWithDuration:(NSTimeInterval)timerDuration { + self.scheduledCheckinTimer = + [NSTimer scheduledTimerWithTimeInterval:timerDuration + target:self + selector:@selector(onScheduledCheckinTimerFired:) + userInfo:nil + repeats:NO]; + // Add some tolerance to the timer, to allow iOS to be more flexible with this timer + self.scheduledCheckinTimer.tolerance = 0.5; +} + +- (void)clearScheduledCheckinTimer { + [self.scheduledCheckinTimer invalidate]; + self.scheduledCheckinTimer = nil; +} + +- (void)onScheduledCheckinTimerFired:(NSTimer *)timer { + [self performScheduledCheckin]; +} + +- (void)performScheduledCheckin { + // No checkin scheduled as of now. + [self clearScheduledCheckinTimer]; + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + FIRInstanceID_WEAKIFY(self); + [self + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + self.checkinRetryCount++; + + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService001, @"Checkin error %@.", + error); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Schedule another checkin + [self scheduleCheckin:NO]; + }); + + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService002, @"Checkin success."); + } + }]; +} + +- (int64_t)calculateNextCheckinRetryIntervalInSeconds { + // persistent failures can lead to overflow prevent that. + if (self.checkinRetryCount >= 10) { + return kMaxCheckinRetryIntervalInSeconds; + } + return MIN(1 << self.checkinRetryCount, kMaxCheckinRetryIntervalInSeconds); +} + +#pragma mark - Checkin Service + +- (BOOL)hasValidCheckinInfo { + return [self.checkinPreferences hasValidCheckinInfo]; +} + +- (void)fetchCheckinInfoWithHandler:(nonnull FIRInstanceIDDeviceCheckinCompletion)handler { + // Perform any changes to self.checkinHandlers and _isCheckinInProgress in a thread-safe way. + @synchronized(self) { + [self.checkinHandlers addObject:handler]; + + if (_isCheckinInProgress) { + // Nothing more to do until our checkin request is done + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress, + @"Checkin is in progress\n"); + return; + } + } + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + [self notifyCheckinHandlersWithCheckin:self.checkinPreferences error:nil]; + return; + } + + @synchronized(self) { + _isCheckinInProgress = YES; + } + [self.checkinService + checkinWithExistingCheckin:self.checkinPreferences + completion:^(FIRInstanceIDCheckinPreferences *checkinPreferences, + NSError *error) { + @synchronized(self) { + self->_isCheckinInProgress = NO; + } + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService003, + @"Failed to checkin device %@", error); + [self notifyCheckinHandlersWithCheckin:nil error:error]; + return; + } + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService004, + @"Successfully got checkin credentials"); + BOOL hasSameCachedPreferences = + [self cachedCheckinMatchesCheckin:checkinPreferences]; + checkinPreferences.hasPreCachedAuthCredentials = hasSameCachedPreferences; + + // Update to the most recent checkin preferences + self.checkinPreferences = checkinPreferences; + + // Save the checkin info to disk + // Keychain might not be accessible, so confirm that checkin preferences can + // be saved + [self.store + saveCheckinPreferences:checkinPreferences + handler:^(NSError *checkinSaveError) { + if (checkinSaveError && !hasSameCachedPreferences) { + // The checkin info was new, but it couldn't be + // written to the Keychain. Delete any stuff that was + // cached in memory. This doesn't delete any + // previously persisted preferences. + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeService004, + @"Unable to save checkin info, resetting " + @"checkin preferences " + "in memory."); + [checkinPreferences reset]; + [self + notifyCheckinHandlersWithCheckin:nil + error: + checkinSaveError]; + } else { + // The checkin is either new, or it was the same (and + // it couldn't be saved). Either way, report that the + // checkin preferences were received successfully. + [self notifyCheckinHandlersWithCheckin: + checkinPreferences + error:nil]; + if (!hasSameCachedPreferences) { + // Checkin is new. + // Notify any listeners that might be waiting for + // checkin to be fetched, such as Firebase + // Messaging (for its MCS connection). + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] + postNotificationName: + kFIRInstanceIDCheckinFetchedNotification + object:nil]; + }); + } + } + }]; + }]; +} + +- (FIRInstanceIDCheckinPreferences *)checkinPreferences { + return _checkinPreferences; +} + +- (void)stopCheckinRequest { + [self.checkinService stopFetching]; +} + +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler { + [self.store removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + self.checkinPreferences = nil; + } + if (handler) { + handler(error); + } + }]; +} + +#pragma mark - Private + +/** + * Goes through the current list of checkin handlers and fires them with the same checkin and/or + * error info. The checkin handlers will get cleared after. + */ +- (void)notifyCheckinHandlersWithCheckin:(nullable FIRInstanceIDCheckinPreferences *)checkin + error:(nullable NSError *)error { + @synchronized(self) { + for (FIRInstanceIDDeviceCheckinCompletion handler in self.checkinHandlers) { + handler(checkin, error); + } + [self.checkinHandlers removeAllObjects]; + } +} + +/** + * Given a |checkin|, it will compare it to the current checkinPreferences to see if the + * deviceID and secretToken are the same. + */ +- (BOOL)cachedCheckinMatchesCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + if (self.checkinPreferences && checkin) { + return ([self.checkinPreferences.deviceID isEqualToString:checkin.deviceID] && + [self.checkinPreferences.secretToken isEqualToString:checkin.secretToken]); + } + return NO; +} +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h new file mode 100644 index 0000000..bccaced --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDBackupExcludedPlist : NSObject + +/** + * Caches the plist contents in memory so we don't hit the disk each time we want + * to query something in the plist. This is loaded lazily i.e. if you write to the + * plist the contents you want to write will be stored here if the write was + * successful. The other case where it is loaded is if you read the plist contents + * by calling `contentAsDictionary`. + * + * In case you write to the plist and then try to read the file using + * `contentAsDictionary` we would just return the cachedPlistContents since it would + * represent the disk contents. + */ +@property(nonatomic, readonly, strong) NSDictionary *cachedPlistContents; + +/** + * Init a backup excluded plist file. + * + * @param fileName The filename for the plist file. + * @param subDirectory The subdirectory in Application Support to save the plist. + * + * @return Helper which allows to read write data to a backup excluded plist. + */ +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory; + +/** + * Write dictionary data to the backup excluded plist file. If the file does not exist + * it would be created before writing to it. + * + * @param dict The data to be written to the plist. + * @param error The error object if any while writing the data. + * + * @return YES if the write was successful else NO. + */ +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error; + +/** + * Delete the backup excluded plist created with the above filename. + * + * @param error The error object if any while deleting the file. + * + * @return YES If the delete was successful else NO. + */ +- (BOOL)deleteFile:(NSError **)error; + +/** + * The contents of the plist file. We also store the contents of the file in-memory. + * If the in-memory contents are valid we return the in-memory contents else we read + * the file from disk. + * + * @return A dictionary object that contains the contents of the plist file if the file + * exists else nil. + */ +- (NSDictionary *)contentAsDictionary; + +/** + * Check if the plist exists on the disk or not. + * + * @return YES if the file exists on the disk else NO. + */ +- (BOOL)doesFileExist; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m new file mode 100644 index 0000000..2c32222 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m @@ -0,0 +1,206 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDBackupExcludedPlist.h" + +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" + +typedef enum : NSUInteger { + FIRInstanceIDPlistDirectoryUnknown, + FIRInstanceIDPlistDirectoryDocuments, + FIRInstanceIDPlistDirectoryApplicationSupport, +} FIRInstanceIDPlistDirectory; + +@interface FIRInstanceIDBackupExcludedPlist () + +@property(nonatomic, readwrite, copy) NSString *fileName; +@property(nonatomic, readwrite, copy) NSString *subDirectoryName; +@property(nonatomic, readwrite, assign) BOOL fileInStandardDirectory; + +@property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents; + +@end + +@implementation FIRInstanceIDBackupExcludedPlist + +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory { + self = [super init]; + if (self) { + _fileName = [fileName copy]; + _subDirectoryName = [subDirectory copy]; +#if TARGET_OS_IOS + _fileInStandardDirectory = [self moveToApplicationSupportSubDirectory:subDirectory]; +#else + // For tvOS and macOS, we never store the content in document folder, so + // the migration is unnecessary. + _fileInStandardDirectory = YES; +#endif + } + return self; +} + +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error { + NSString *path = [self plistPathInDirectory:[self plistDirectory]]; + if (![dict writeToFile:path atomically:YES]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000, + @"Failed to write to %@.plist", self.fileName); + return NO; + } + + // Successfully wrote contents -- change the in-memory contents + self.cachedPlistContents = [dict copy]; + + _FIRInstanceIDDevAssert([[NSFileManager defaultManager] fileExistsAtPath:path], + @"Error writing data to non-backed up plist %@.plist", self.fileName); + + NSURL *URL = [NSURL fileURLWithPath:path]; + if (error) { + *error = nil; + } + + NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ] + error:error]; + if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) { + return YES; + } + + BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error]; + if (!success) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001, + @"Error excluding %@ from backup, %@", [URL lastPathComponent], + error ? *error : @""); + } + return success; +} + +- (BOOL)deleteFile:(NSError **)error { + BOOL success = YES; + NSString *path = [self plistPathInDirectory:[self plistDirectory]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + success = [[NSFileManager defaultManager] removeItemAtPath:path error:error]; + } + // remove the in-memory contents + self.cachedPlistContents = nil; + return success; +} + +- (NSDictionary *)contentAsDictionary { + if (!self.cachedPlistContents) { + NSString *path = [self plistPathInDirectory:[self plistDirectory]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path]; + } + } + return self.cachedPlistContents; +} + +- (BOOL)moveToApplicationSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + // This only going to happen inside iOS so it is an applicationSupportDirectory. + NSString *applicationSupportDirPath = directoryPaths.lastObject; + NSArray *components = @[ applicationSupportDirPath, subDirectoryName ]; + NSString *subDirectoryPath = [NSString pathWithComponents:components]; + BOOL hasSubDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + // Cannot move to non-existent directory + return NO; + } + + if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryDocuments]) { + NSString *oldPlistPath = [self plistPathInDirectory:FIRInstanceIDPlistDirectoryDocuments]; + NSString *newPlistPath = + [self plistPathInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport]; + if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport]) { + // File exists in both Documents and ApplicationSupport + return NO; + } + NSError *moveError; + if (![[NSFileManager defaultManager] moveItemAtPath:oldPlistPath + toPath:newPlistPath + error:&moveError]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist002, + @"Failed to move file %@ from %@ to %@. Error: %@", self.fileName, + oldPlistPath, newPlistPath, moveError); + return NO; + } + } + // We moved the file if it existed, otherwise we didn't need to do anything + return YES; +} + +- (BOOL)doesFileExist { + return [self doesFileExistInDirectory:[self plistDirectory]]; +} + +#pragma mark - Private + +- (FIRInstanceIDPlistDirectory)plistDirectory { + if (_fileInStandardDirectory) { + return FIRInstanceIDPlistDirectoryApplicationSupport; + } else { + return FIRInstanceIDPlistDirectoryDocuments; + }; +} + +- (NSString *)plistPathInDirectory:(FIRInstanceIDPlistDirectory)directory { + return [self pathWithName:self.fileName inDirectory:directory]; +} + +- (NSString *)pathWithName:(NSString *)plistName + inDirectory:(FIRInstanceIDPlistDirectory)directory { + NSArray *directoryPaths; + NSArray *components = @[]; + NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", plistName]; + switch (directory) { + case FIRInstanceIDPlistDirectoryDocuments: + directoryPaths = + NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + components = @[ directoryPaths.lastObject, plistNameWithExtension ]; + break; + + case FIRInstanceIDPlistDirectoryApplicationSupport: + directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + break; + + default: + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum, + @"Invalid plist directory type: %lu", (unsigned long)directory); + NSAssert(NO, @"Invalid plist directory type: %lu", (unsigned long)directory); + break; + } + + return [NSString pathWithComponents:components]; +} + +- (BOOL)doesFileExistInDirectory:(FIRInstanceIDPlistDirectory)directory { + NSString *path = [self plistPathInDirectory:directory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h new file mode 100644 index 0000000..a62fad1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +@interface FIRInstanceIDCheckinPreferences (Internal) + +/** + * Parse the checkin auth credentials saved in the Keychain to initialize checkin + * preferences. + * + * @param keychainContent The checkin auth credentials saved in the Keychain. + * + * @return A valid checkin preferences object if the checkin auth credentials in the + * keychain can be parsed successfully else nil. + */ ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent; + +/** + * Default initializer for InstanceID checkin preferences. + * + * @param deviceID The deviceID for the app. + * @param secretToken The secret token the app uses to authenticate with the server. + * + * @return A checkin preferences object with given deviceID and secretToken. + */ +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken; + +/** + * Update checkin preferences from the preferences dict persisted as a plist. The dict contains + * all the checkin preferences retrieved from the server except the deviceID and secret which + * are stored in the Keychain. + * + * @param checkinPlistContent The checkin preferences saved in a plist on the disk. + */ +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent; + +/** + * Reset the current checkin preferences object. + */ +- (void)reset; + +/** + * The string that contains the checkin auth credentials i.e. deviceID and secret. This + * needs to be stored in the Keychain. + * + * @return The checkin auth credential string containing the deviceID and secret. + */ +- (NSString *)checkinKeychainContent; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m new file mode 100644 index 0000000..88cc40a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences+Internal.h" + +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kCheckinKeychainContentSeparatorString = @"|"; + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +@end + +@implementation FIRInstanceIDCheckinPreferences (Internal) + ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent { + NSString *deviceID = [self checkinDeviceIDFromKeychainContent:keychainContent]; + NSString *secret = [self checkinSecretFromKeychainContent:keychainContent]; + if ([deviceID length] && [secret length]) { + return [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceID secretToken:secret]; + } else { + return nil; + } +} + +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken { + self = [super init]; + if (self) { + self.deviceID = [deviceID copy]; + self.secretToken = [secretToken copy]; + } + return self; +} + +- (void)reset { + self.deviceID = nil; + self.secretToken = nil; + self.digest = nil; + self.versionInfo = nil; + self.gServicesData = nil; + self.deviceDataVersion = nil; + self.lastCheckinTimestampMillis = 0; +} + +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent { + for (NSString *key in checkinPlistContent) { + if ([kFIRInstanceIDDigestStringKey isEqualToString:key]) { + self.digest = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDVersionInfoStringKey isEqualToString:key]) { + self.versionInfo = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDLastCheckinTimeKey isEqualToString:key]) { + self.lastCheckinTimestampMillis = [checkinPlistContent[key] longLongValue]; + } else if ([kFIRInstanceIDGServicesDictionaryKey isEqualToString:key]) { + self.gServicesData = [checkinPlistContent[key] mutableCopy]; + } else if ([kFIRInstanceIDDeviceDataVersionKey isEqualToString:key]) { + self.deviceDataVersion = [checkinPlistContent[key] copy]; + } + // Otherwise we have some keys we don't care about + } +} + +- (NSString *)checkinKeychainContent { + if ([self.deviceID length] && [self.secretToken length]) { + return [NSString stringWithFormat:@"%@%@%@", self.deviceID, + kCheckinKeychainContentSeparatorString, self.secretToken]; + } else { + return nil; + } +} + ++ (NSString *)checkinDeviceIDFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:0]; +} + ++ (NSString *)checkinSecretFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:1]; +} + ++ (NSString *)checkinKeychainContent:(NSString *)keychainContent forIndex:(int)index { + NSArray *keychainComponents = + [keychainContent componentsSeparatedByString:kCheckinKeychainContentSeparatorString]; + if (index >= 0 && index < 2 && [keychainComponents count] == 2) { + return keychainComponents[index]; + } else { + return nil; + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h new file mode 100644 index 0000000..fe459af --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The preferences InstanceID loads from checkin server. The deviceID and secret that checkin + * provides is used to authenticate all future requests to the server. Besides the deviceID + * and secret the other information that checkin provides is stored in a plist on the device. + * The deviceID and secret are persisted in the device keychain. + */ +@interface FIRInstanceIDCheckinPreferences : NSObject + +/** + * DeviceID and secretToken are the checkin auth credentials and are stored in the Keychain. + */ +@property(nonatomic, readonly, copy) NSString *deviceID; +@property(nonatomic, readonly, copy) NSString *secretToken; + +/** + * All the other checkin preferences other than deviceID and secret are stored in a plist. + */ +@property(nonatomic, readonly, copy) NSString *deviceDataVersion; +@property(nonatomic, readonly, copy) NSString *digest; +@property(nonatomic, readonly, copy) NSString *versionInfo; +@property(nonatomic, readonly, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readonly, assign) int64_t lastCheckinTimestampMillis; + +/** + * The content retrieved from checkin server that should be persisted in a plist. This + * doesn't contain the deviceID and secret which are stored in the Keychain since they + * should be more private. + * + * @return The checkin preferences that should be persisted in a plist. + */ +- (NSDictionary *)checkinPlistContents; + +/** + * Return whether checkin info exists, valid or not. + */ +- (BOOL)hasCheckinInfo; + +/** + * Verify if checkin preferences are valid or not. + * + * @return YES if valid checkin preferences else NO. + */ +- (BOOL)hasValidCheckinInfo; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m new file mode 100644 index 0000000..2479a85 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m @@ -0,0 +1,97 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +#import +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDUtilities.h" + +const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval = 7 * 24 * 60 * 60; // 7 days. + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +// This flag indicates that we have already saved the above deviceID and secret +// to our keychain and hence we don't need to save again. This is helpful since +// on checkin refresh we can avoid writing to the Keychain which can sometimes +// be very buggy. For info check this https://forums.developer.apple.com/thread/4743 +@property(nonatomic, readwrite, assign) BOOL hasPreCachedAuthCredentials; + +@end + +@implementation FIRInstanceIDCheckinPreferences + +- (NSDictionary *)checkinPlistContents { + NSMutableDictionary *checkinPlistContents = [NSMutableDictionary dictionary]; + checkinPlistContents[kFIRInstanceIDDigestStringKey] = self.digest ?: @""; + checkinPlistContents[kFIRInstanceIDVersionInfoStringKey] = self.versionInfo ?: @""; + checkinPlistContents[kFIRInstanceIDDeviceDataVersionKey] = self.deviceDataVersion ?: @""; + checkinPlistContents[kFIRInstanceIDLastCheckinTimeKey] = @(self.lastCheckinTimestampMillis); + checkinPlistContents[kFIRInstanceIDGServicesDictionaryKey] = + [self.gServicesData count] ? self.gServicesData : @{}; + return checkinPlistContents; +} + +- (BOOL)hasCheckinInfo { + return (self.deviceID.length && self.secretToken.length); +} + +- (BOOL)hasValidCheckinInfo { + int64_t currentTimestampInMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + int64_t timeSinceLastCheckinInMillis = currentTimestampInMillis - self.lastCheckinTimestampMillis; + _FIRInstanceIDDevAssert(timeSinceLastCheckinInMillis >= 0, + @"FCM error: cannot have last checkin timestamp in future"); + BOOL hasCheckinInfo = [self hasCheckinInfo]; + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + // If it's app's first time open and checkin is already fetched and no locale information is + // stored, then checkin info is valid. We should not checkin again because locale is considered + // "changed". + if (hasCheckinInfo && !lastLocale) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return YES; + } + + // If locale has changed, checkin info is no longer valid. + // Also update locale information if changed. (Only do it here not in token refresh) + if (FIRInstanceIDHasLocaleChanged()) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return NO; + } + + return (hasCheckinInfo && + (timeSinceLastCheckinInMillis / 1000.0 < kFIRInstanceIDDefaultCheckinInterval)); +} + +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials { + _hasPreCachedAuthCredentials = hasPreCachedAuthCredentials; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h new file mode 100644 index 0000000..23b55e1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +/** Checkin refresh interval. **/ +FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval; + +@interface FIRInstanceIDCheckinPreferences () + +- (BOOL)hasPreCachedAuthCredentials; +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h new file mode 100644 index 0000000..cc97e47 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstanceIDUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +// keys in Checkin preferences +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceAuthIdKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSecretTokenKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDigestStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDLastCheckinTimeKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDVersionInfoStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDGServicesDictionaryKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceDataVersionKey; + +@class FIRInstanceIDCheckinPreferences; + +/** + * @related FIRInstanceIDCheckinService + * + * The completion handler invoked once the fetch from Checkin server finishes. + * For successful fetches we returned checkin information by the checkin service + * and `nil` error, else we return the appropriate error object as reported by the + * Checkin Service. + * + * @param checkinPreferences The checkin preferences as fetched from the server. + * @param error The error object which fetching GServices data. + */ +typedef void (^FIRInstanceIDDeviceCheckinCompletion)( + FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error); + +/** + * Register the device with Checkin Service and get back the `authID`, `secret + * token` etc. for the client. Checkin results are cached in the + * `FIRInstanceIDCache` and periodically refreshed to prevent them from being stale. + * Each client needs to register with checkin before registering with InstanceID. + */ +@interface FIRInstanceIDCheckinService : NSObject + +/** + * Execute a device checkin request to obtain an deviceID, secret token, + * gService data. + * + * @param existingCheckin An existing checkin preference object, if available. + * @param completion Completion hander called on success or failure of device checkin. + */ +- (void)checkinWithExistingCheckin:(nullable FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion; + +/** + * This would stop any request that the service made to the checkin backend and also + * release any callback handlers that it holds. + */ +- (void)stopFetching; + +/** + * Set test block for mock testing network requests. + * + * @param block The block to invoke as a mock response from the network. + */ ++ (void)setCheckinTestBlock:(nullable FIRInstanceIDURLRequestTestBlock)block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m new file mode 100644 index 0000000..be5b01a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m @@ -0,0 +1,235 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin"; + +// keys in Checkin preferences +NSString *const kFIRInstanceIDDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey"; +NSString *const kFIRInstanceIDSecretTokenKey = @"GMSInstanceIDSecretTokenKey"; +NSString *const kFIRInstanceIDDigestStringKey = @"GMSInstanceIDDigestKey"; +NSString *const kFIRInstanceIDLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey"; +NSString *const kFIRInstanceIDVersionInfoStringKey = @"GMSInstanceIDVersionInfo"; +NSString *const kFIRInstanceIDGServicesDictionaryKey = @"GMSInstanceIDGServicesData"; +NSString *const kFIRInstanceIDDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion"; + +static NSUInteger const kCheckinType = 2; // DeviceType IOS in l/w/a/_checkin.proto +static NSUInteger const kCheckinVersion = 2; +static NSUInteger const kFragment = 0; + +static FIRInstanceIDURLRequestTestBlock testBlock; + +@interface FIRInstanceIDCheckinService () + +@property(nonatomic, readwrite, strong) NSURLSession *session; + +@end + +@implementation FIRInstanceIDCheckinService +; + +- (instancetype)init { + self = [super init]; + if (self) { + // Create an URLSession once, even though checkin should happen about once a day + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + config.allowsCellularAccess = YES; + _session = [NSURLSession sessionWithConfiguration:config]; + _session.sessionDescription = @"com.google.iid-checkin"; + } + return self; +} + +- (void)dealloc { + testBlock = nil; + [self.session invalidateAndCancel]; +} + +- (void)checkinWithExistingCheckin:(FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion { + _FIRInstanceIDDevAssert(completion != nil, @"completion required"); + + if (self.session == nil) { + FIRInstanceIDLoggerError(kFIRIntsanceIDInvalidNetworkSession, + @"Inconsistent state: NSURLSession has been invalidated"); + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]; + completion(nil, error); + return; + } + + NSURL *url = [NSURL URLWithString:kDeviceCheckinURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; + NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin]; + NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters + options:0 + error:nil]; + request.HTTPMethod = @"POST"; + request.HTTPBody = checkinData; + + void (^handler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService000, + @"Device checkin HTTP fetch error. Error Code: %ld", + (long)error.code); + completion(nil, error); + return; + } + + NSError *serializationError; + NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&serializationError]; + if (serializationError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService001, + @"Error serializing json object. Error Code: %ld", + _FIRInstanceID_L(serializationError.code)); + completion(nil, serializationError); + return; + } + + NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue]; + NSString *secretToken = [dataResponse[@"security_token"] stringValue]; + if ([deviceAuthID length] == 0) { + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidRequest]; + completion(nil, error); + return; + } + + int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue]; + int64_t currentTimestampMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + // Somehow the server clock gets out of sync with the device clock. + // Reset the last checkin timestamp in case this happens. + if (lastCheckinTimestampMillis > currentTimestampMillis) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeService002, @"Invalid last checkin timestamp %@ in future.", + [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]); + lastCheckinTimestampMillis = currentTimestampMillis; + } + + NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @""; + NSString *digest = dataResponse[@"digest"] ?: @""; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService003, + @"Checkin successful with authId: %@, " + @"digest: %@, " + @"lastCheckinTimestamp: %lld", + deviceAuthID, digest, lastCheckinTimestampMillis); + + NSString *versionInfo = dataResponse[@"version_info"] ?: @""; + NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary]; + + // Read gServices data. + NSArray *flatSettings = dataResponse[@"setting"]; + for (NSDictionary *dict in flatSettings) { + if (dict[@"name"] && dict[@"value"]) { + gservicesData[dict[@"name"]] = dict[@"value"]; + } else { + _FIRInstanceIDDevAssert(NO, @"Invalid setting in checkin response: (%@: %@)", + dict[@"name"], dict[@"value"]); + } + } + + FIRInstanceIDCheckinPreferences *checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceAuthID + secretToken:secretToken]; + NSDictionary *preferences = @{ + kFIRInstanceIDDigestStringKey : digest, + kFIRInstanceIDVersionInfoStringKey : versionInfo, + kFIRInstanceIDLastCheckinTimeKey : @(lastCheckinTimestampMillis), + kFIRInstanceIDGServicesDictionaryKey : gservicesData, + kFIRInstanceIDDeviceDataVersionKey : deviceDataVersionInfo, + }; + [checkinPreferences updateWithCheckinPlistContents:preferences]; + completion(checkinPreferences, nil); + }; + // Test block + if (testBlock) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService005, + @"Test block set, will not hit the server"); + testBlock(request, handler); + return; + } + + NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler]; + [task resume]; +} + +- (void)stopFetching { + [self.session invalidateAndCancel]; + // The session cannot be reused after invalidation. Dispose it to prevent accident reusing. + self.session = nil; +} + +#pragma mark - Private + +- (NSDictionary *)checkinParametersWithExistingCheckin: + (nullable FIRInstanceIDCheckinPreferences *)checkinPreferences { + NSString *deviceModel = FIRInstanceIDDeviceModel(); + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion]; + + // Get locale from GCM if GCM exists else use system API. + NSString *locale = FIRInstanceIDCurrentLocale(); + + NSInteger userNumber = 0; // Multi Profile may change this. + NSInteger userSerialNumber = 0; // Multi Profile may change this + + uint32_t loggingID = arc4random(); + NSString *timeZone = [NSTimeZone localTimeZone].name; + int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis; + + NSDictionary *checkinParameters = @{ + @"checkin" : @{ + @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion}, + @"type" : @(kCheckinType), + @"user_number" : @(userNumber), + @"last_checkin_msec" : @(lastCheckingTimestampMillis), + }, + @"fragment" : @(kFragment), + @"logging_id" : @(loggingID), + @"locale" : locale, + @"version" : @(kCheckinVersion), + @"digest" : checkinPreferences.digest ?: @"", + @"timezone" : timeZone, + @"user_serial_number" : @(userSerialNumber), + @"id" : @([checkinPreferences.deviceID longLongValue]), + @"security_token" : @([checkinPreferences.secretToken longLongValue]), + }; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService006, @"Checkin parameters: %@", + checkinParameters); + return checkinParameters; +} + ++ (void)setCheckinTestBlock:(FIRInstanceIDURLRequestTestBlock)block { + testBlock = [block copy]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h new file mode 100644 index 0000000..5e1b119 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h @@ -0,0 +1,108 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; + +// These values exposed for testing +extern NSString *const kFIRInstanceIDCheckinKeychainService; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainService; + +/** + * Checkin preferences backing store. + */ +@interface FIRInstanceIDCheckinStore : NSObject + +/** + * Designated Initializer. Initialize a checkin store with the given backup excluded + * plist filename. + * + * @param checkinFilename The backup excluded plist filename to persist checkin + * preferences. + * + * @param subDirectoryName Sub-directory in standard directory where we write + * InstanceID plist. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName; + +/** + * Initialize a checkin store with the given backup excluded plist and keychain. + * + * @param plist The backup excluded plist to persist checkin preferences. + * @param keychain The keychain used to persist checkin auth preferences. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain; + +/** + * Checks whether the backup excluded checkin preferences are present on the disk or not. + * + * @return YES if the backup excluded checkin plist exists on the disks else NO. + */ +- (BOOL)hasCheckinPlist; + +#pragma mark - Save + +/** + * Save the checkin preferences to backing store. + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler; + +#pragma mark - Delete + +/** + * Remove the cached checkin preferences. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler; + +#pragma mark - Get + +/** + * Get the cached device secret. If we cannot access it for some reason we + * return the appropriate error object. + * + * @return The cached checkin preferences if present else nil. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Migrate the checkin item from old service/account to the new one. + * The new account is dynamic as it uses bundle ID. + * This is to ensure checkin is not shared across apps, but still the same + * if app has used GCM before. + * This call should only happen once. + * + */ +- (void)migrateCheckinItemIfNeeded; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m new file mode 100644 index 0000000..99715a5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m @@ -0,0 +1,238 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kFIRInstanceIDCheckinKeychainGeneric = @"com.google.iid"; + +NSString *const kFIRInstanceIDCheckinKeychainService = @"com.google.iid.checkin"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount = @"com.google.iid.checkin-account"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainService = @"com.google.iid.checkin-service"; + +// Checkin plist used to have the deviceID and secret stored in them and that's why they +// had 6 items in it. Since the deviceID and secret have been moved to the keychain +// there would only be 4 items. +static const NSInteger kOldCheckinPlistCount = 6; + +@interface FIRInstanceIDCheckinStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; +// Checkin will store items under +// Keychain account: , +// Keychain service: |kFIRInstanceIDCheckinKeychainService| +@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount; + +@end + +@implementation FIRInstanceIDCheckinStore + +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName { + FIRInstanceIDBackupExcludedPlist *plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinFilename + subDirectory:subDirectoryName]; + + FIRInstanceIDAuthKeychain *keychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDCheckinKeychainGeneric]; + return [self initWithCheckinPlist:plist keychain:keychain]; +} + +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _plist = plist; + _keychain = keychain; + } + return self; +} + +- (BOOL)hasCheckinPlist { + return [self.plist doesFileExist]; +} + +- (NSString *)bundleIdentifierForKeychainAccount { + static NSString *bundleIdentifier; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundleIdentifier = FIRInstanceIDAppIdentifier(); + }); + return bundleIdentifier; +} + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + NSDictionary *checkinPlistContents = [preferences checkinPlistContents]; + NSString *checkinKeychainContent = [preferences checkinKeychainContent]; + + if (![checkinKeychainContent length]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore000, + @"Failed to get checkin keychain content from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + if (![checkinPlistContents count]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore001, + @"Failed to get checkin plist contents from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + + // Save all other checkin preferences in a plist + NSError *error; + if (![self.plist writeDictionary:checkinPlistContents error:&error]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore003, + @"Failed to save checkin plist contents." + @"Will delete auth credentials"); + [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + if (handler) { + handler(error); + } + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved, + @"Checkin plist file is saved"); + + // Save the deviceID and secret in the Keychain + if (!preferences.hasPreCachedAuthCredentials) { + NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding]; + [self.keychain setData:data + forService:kFIRInstanceIDCheckinKeychainService + accessibility:nil + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + } else { + handler(nil); + } +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler { + // Delete the checkin preferences plist first to avoid delay. + NSError *deletePlistError; + if (![self.plist deleteFile:&deletePlistError]) { + handler(deletePlistError); + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted, + @"Deleted checkin plist file."); + // Remove deviceID and secret from Keychain + [self.keychain + removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + // Try to remove from old location as well because migration + // is no longer needed. Consider this is either a fresh install + // or an identity wipe. + [self.keychain + removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + handler(error); + }]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + // Query the keychain for deviceID and secret + NSData *item = [self.keychain dataForService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount]; + + // Check info found in keychain + NSString *checkinKeychainContent = [[NSString alloc] initWithData:item + encoding:NSUTF8StringEncoding]; + FIRInstanceIDCheckinPreferences *checkinPreferences = + [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:checkinKeychainContent]; + + NSDictionary *checkinPlistContents = [self.plist contentAsDictionary]; + + NSString *plistDeviceAuthID = checkinPlistContents[kFIRInstanceIDDeviceAuthIdKey]; + NSString *plistSecretToken = checkinPlistContents[kFIRInstanceIDSecretTokenKey]; + + // If deviceID and secret not found in the keychain verify that we don't have them in the + // checkin preferences plist. + if (![checkinPreferences.deviceID length] && ![checkinPreferences.secretToken length]) { + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + // Couldn't find checkin credentials in keychain but found them in the plist. + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } else { + // Couldn't find checkin credentials in keychain nor plist + return nil; + } + } else if (kOldCheckinPlistCount == checkinPlistContents.count) { + // same check as above but just to be extra sure that we cover all upgrade cases properly. + // TODO(chliangGoogle): Remove this case, after verifying it's not needed + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } + } + + [checkinPreferences updateWithCheckinPlistContents:checkinPlistContents]; + return checkinPreferences; +} + +- (void)migrateCheckinItemIfNeeded { + // Check for checkin in the old location, using the legacy keys + // Query the keychain for deviceID and secret + NSData *dataInOldLocation = + [self.keychain dataForService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount]; + if (dataInOldLocation) { + // Save to new location + [self.keychain setData:dataInOldLocation + forService:kFIRInstanceIDCheckinKeychainService + accessibility:NULL + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + // Remove from old location + [self.keychain removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h new file mode 100644 index 0000000..dcb5429 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A generic class to combine several handler blocks into a single block in a thread-safe manner + */ +@interface FIRInstanceIDCombinedHandler : NSObject + +- (void)addHandler:(void (^)(ResultType _Nullable result, NSError* _Nullable error))handler; +- (void (^)(ResultType _Nullable result, NSError* _Nullable error))combinedHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m new file mode 100644 index 0000000..bc6be6c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCombinedHandler.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRInstanseIDHandler)(id _Nullable result, NSError *_Nullable error); + +@interface FIRInstanceIDCombinedHandler () +@property(atomic, readonly, strong) NSMutableArray *handlers; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstanceIDCombinedHandler + +- (instancetype)init { + self = [super init]; + if (self) { + _handlers = [NSMutableArray array]; + } + return self; +} + +- (void)addHandler:(FIRInstanseIDHandler)handler { + if (!handler) { + return; + } + + @synchronized(self) { + [self.handlers addObject:handler]; + } +} + +- (FIRInstanseIDHandler)combinedHandler { + FIRInstanseIDHandler combinedHandler = nil; + + @synchronized(self) { + NSArray *handlers = [self.handlers copy]; + combinedHandler = ^(id result, NSError *error) { + for (FIRInstanseIDHandler handler in handlers) { + handler(result, error); + } + }; + } + + return combinedHandler; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h new file mode 100644 index 0000000..cd2e131 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#pragma mark - Commands + +/** + * Value included in a structured response or GCM message from IID, indicating + * an identity reset. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST; + +#pragma mark - Notifications + +/// Notification used to deliver GCM messages for InstanceID. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification; + +#pragma mark - Miscellaneous + +/// The scope used to save the IID "*" scope token. This is used for saving the +/// IID auth token that we receive from the server. This feature was never +/// implemented on the server side. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAllScopeIdentifier; +/// The scope used to save the IID "*" scope token. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultTokenScope; + +/// Subdirectory in search path directory to store InstanceID preferences. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSubDirectoryName; + +/// The key for APNS token in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSKey; + +/// The key for APNS token environment type in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + +/// The key for GMP AppID sent in registration requests. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey; + +/// The key to enable auto-register by swizzling AppDelegate's methods. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey; + +/// Error code for missing entitlements in Keychain. iOS Keychain error +/// https://forums.developer.apple.com/thread/4743 +FOUNDATION_EXPORT const int kFIRInstanceIDSecMissingEntitlementErrorCode; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m new file mode 100644 index 0000000..81f4620 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDConstants.h" + +// Commands +NSString *const kFIRInstanceID_CMD_RST = @"RST"; + +// NOTIFICATIONS +NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenNotification = @"com.firebase.iid.notif.fcm-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification = + @"com.firebase.iid.notif.fcm-token-fail"; + +NSString *const kFIRInstanceIDIdentityInvalidatedNotification = @"com.google.iid.identity-invalid"; + +// Miscellaneous +NSString *const kFIRInstanceIDAllScopeIdentifier = @"iid-all"; +NSString *const kFIRInstanceIDDefaultTokenScope = @"*"; +NSString *const kFIRInstanceIDSubDirectoryName = @"Google/FirebaseInstanceID"; + +// Registration Options +NSString *const kFIRInstanceIDTokenOptionsAPNSKey = @"apns_token"; +NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey = @"apns_sandbox"; +NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey = @"gmp_app_id"; + +NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +// iOS Keychain error https://forums.developer.apple.com/thread/4743 +// An undocumented error code hence need to be redeclared. +const int kFIRInstanceIDSecMissingEntitlementErrorCode = -34018; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h new file mode 100644 index 0000000..764dfe5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRInstanceIDLib_FIRInstanceIDDefines_h +#define FIRInstanceIDLib_FIRInstanceIDDefines_h + +#define _FIRInstanceID_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRInstanceID_VERBOSE_LOGGING) +#define FIRInstanceID_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRInstanceID_DEV_VERBOSE_LOG(...) \ + do { \ + } while (0) +#endif // VERBOSE_LOGGING + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRInstanceID_WEAKNAME(VAR) VAR##_weak_ + +#define FIRInstanceID_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRInstanceID_WEAKNAME(VAR) = (VAR); + +#define FIRInstanceID_STRONGIFY(VAR) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") \ + __strong __typeof__(VAR) VAR = _FIRInstanceID_WEAKNAME(VAR); \ + _Pragma("clang diagnostic pop") + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRInstanceID_L +#define _FIRInstanceID_L(v) (long)(v) +#endif + +#endif + +// Debug Assert +#ifndef _FIRInstanceIDDevAssert +// we directly invoke the NSAssert handler so we can pass on the varargs +// (NSAssert doesn't have a macro we can use that takes varargs) +#if !defined(NS_BLOCK_ASSERTIONS) +#define _FIRInstanceIDDevAssert(condition, ...) \ + do { \ + if (!(condition)) { \ + [[NSAssertionHandler currentHandler] \ + handleFailureInFunction:(NSString *)[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ + file:(NSString *)[NSString stringWithUTF8String:__FILE__] \ + lineNumber:__LINE__ \ + description:__VA_ARGS__]; \ + } \ + } while (0) +#else // !defined(NS_BLOCK_ASSERTIONS) +#define _FIRInstanceIDDevAssert(condition, ...) \ + do { \ + } while (0) +#endif // !defined(NS_BLOCK_ASSERTIONS) + +#endif // _FIRInstanceIDDevAssert diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h new file mode 100644 index 0000000..a1aa5e1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h @@ -0,0 +1,78 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDKeyPair : NSObject + +- (instancetype)init __attribute__(( + unavailable("Use -initWithPrivateKey:publicKey:publicKeyData:privateKeyData: instead."))); +; + +/** + * Initialize a new 2048 bit RSA keypair. This also stores the keypair in the Keychain + * Preferences. + * + * @param publicKey The publicKey stored in Keychain. + * @param privateKey The privateKey stored in Keychain. + * @param publicKeyData The publicKey in NSData format. + * @param privateKeyData The privateKey in NSData format. + * + * @return A new KeyPair instance with the generated public and private key. + */ +- (instancetype)initWithPrivateKey:(SecKeyRef)privateKey + publicKey:(SecKeyRef)publicKey + publicKeyData:(NSData *)publicKeyData + privateKeyData:(NSData *)privateKeyData NS_DESIGNATED_INITIALIZER; + +/** + * The public key in the RSA 20148 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's public key. + */ +@property(nonatomic, readonly, strong) NSData *publicKeyData; + +/** + * The private key in the RSA 20148 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's private key. + */ +@property(nonatomic, readonly, strong) NSData *privateKeyData; + +#pragma mark - Info + +/** + * Checks if the private and public keyPair are valid or not. + * + * @return YES if keypair is valid else NO. + */ +- (BOOL)isValid; + +/** + * The public key in the RSA 2048 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's public key. + */ +- (SecKeyRef)publicKey; + +/** + * The private key in the RSA 2048 bit generated KeyPair. + * + * @return The 2048 bit RSA KeyPair's private key. + */ +- (SecKeyRef)privateKey; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m new file mode 100644 index 0000000..52b27c2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeyPair.h" + +#import + +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDKeyPair () { + SecKeyRef _privateKey; + SecKeyRef _publicKey; +} + +@property(nonatomic, readwrite, strong) NSData *publicKeyData; +@property(nonatomic, readwrite, strong) NSData *privateKeyData; +@end + +@implementation FIRInstanceIDKeyPair +- (instancetype)initWithPrivateKey:(SecKeyRef)privateKey + publicKey:(SecKeyRef)publicKey + publicKeyData:(NSData *)publicKeyData + privateKeyData:(NSData *)privateKeyData { + self = [super init]; + if (self) { + _privateKey = privateKey; + _publicKey = publicKey; + _publicKeyData = publicKeyData; + _privateKeyData = privateKeyData; + } + return self; +} + +- (void)dealloc { + if (_privateKey) { + CFRelease(_privateKey); + } + if (_publicKey) { + CFRelease(_publicKey); + } +} + +#pragma mark - Info + +- (BOOL)isValid { + return _privateKey != NULL && _publicKey != NULL; +} + +- (SecKeyRef)publicKey { + return _publicKey; +} + +- (SecKeyRef)privateKey { + return _privateKey; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h new file mode 100644 index 0000000..02c2896 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDKeyPair; + +extern NSString *const kFIRInstanceIDKeyPairSubType; + +@class FIRInstanceIDKeyPairStore; + +@interface FIRInstanceIDKeyPairStore : NSObject + +/** + * Invalidates the cached keypairs in the Keychain, if needed. The keypair metadata plist is + * checked for existence. If the plist file does not exist, it is a signal of a new installation, + * and therefore the key pairs are not valid. + * + * Returns YES if keypair has been invalidated. + */ +- (BOOL)invalidateKeyPairsIfNeeded; + +/** + * Delete the cached RSA keypair from Keychain with the given subtype. + * + * @param subtype The subtype used to cache the RSA keypair in Keychain. + * @param handler The callback handler which is invoked when the keypair deletion is + * complete, with an error if there is any. + */ +- (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype handler:(void (^)(NSError *))handler; + +/** + * Delete the plist that caches KeyPair generation timestamps. + * + * @param error The error if any while deleting the plist else nil. + * + * @return YES if the delete was successful else NO. + */ +- (BOOL)removeKeyPairCreationTimePlistWithError:(NSError **)error; + +/** + * Loads a cached KeyPair if it exists in the Keychain else generate a new + * one. If a keyPair already exists in memory this will just return that. This should + * not be called from the main thread since it could potentially lead to creating a new + * RSA-2048 bit keyPair which is an expensive operation. + * + * @param error The error, if any, while accessing the Keychain. + * + * @return A valid 2048 bit RSA key pair. + */ +- (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error; + +/** + * Check if the Keychain has any cached keypairs or not. + * + * @return YES if the Keychain has cached RSA KeyPairs else NO. + */ +- (BOOL)hasCachedKeyPairs; + +/** + * Return an identifier for the app instance. The result is a short identifier that can + * be used as a key when storing information about the app. This method will return the same + * ID as long as the application identity remains active. If the identity has been revoked or + * expired the method will generate and return a new identifier. + * + * @param error The error if any while loading the RSA KeyPair. + * + * @return The identifier, as url safe string. + */ +- (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m new file mode 100644 index 0000000..20b5cea --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m @@ -0,0 +1,530 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeyPairStore.h" + +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kFIRInstanceIDKeyPairStoreFileName = @"com.google.iid-keypair"; + +static NSString *const kFIRInstanceIDStoreKeyGenerationTime = @"cre"; + +static NSString *const kFIRInstanceIDStoreKeyPrefix = @"com.google.iid-"; +static NSString *const kFIRInstanceIDStoreKeyPublic = @"|P|"; +static NSString *const kFIRInstanceIDStoreKeyPrivate = @"|K|"; +static NSString *const kFIRInstanceIDStoreKeySubtype = @"|S|"; + +static NSString *const kFIRInstanceIDKeyPairPublicTagPrefix = @"com.google.iid.keypair.public-"; +static NSString *const kFIRInstanceIDKeyPairPrivateTagPrefix = @"com.google.iid.keypair.private-"; + +static const int kMaxMissingEntitlementErrorCount = 3; + +NSString *const kFIRInstanceIDKeyPairSubType = @""; + +// Query the key with NSData format +NSData *FIRInstanceIDKeyDataWithTag(NSString *tag) { + _FIRInstanceIDDevAssert([tag length], @"Invalid tag for keychain specified"); + if (![tag length]) { + return NULL; + } + NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, YES); + CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey]; + if (!result) { + return NULL; + } + return (__bridge NSData *)result; +} + +// Query the key given a tag +SecKeyRef FIRInstanceIDCachedKeyRefWithTag(NSString *tag) { + _FIRInstanceIDDevAssert([tag length], @"Invalid tag for keychain specified"); + if (!tag.length) { + return NULL; + } + NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, NO); + CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey]; + return (SecKeyRef)result; +} + +// Check if keypair has been migrated from the legacy to the new version +BOOL FIRInstanceIDHasMigratedKeyPair(NSString *legacyPublicKeyTag, NSString *newPublicKeyTag) { + NSData *oldPublicKeyData = FIRInstanceIDKeyDataWithTag(legacyPublicKeyTag); + NSData *newPublicKeyData = FIRInstanceIDKeyDataWithTag(newPublicKeyTag); + return [oldPublicKeyData isEqualToData:newPublicKeyData]; +} + +// The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain +// environments. +NSString *FIRInstanceIDLegacyPublicTagWithSubtype(NSString *subtype) { + NSString *prefix = kFIRInstanceIDStoreKeyPrefix; + return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPublic]; +} + +// The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain +// environments. +NSString *FIRInstanceIDLegacyPrivateTagWithSubtype(NSString *subtype) { + NSString *prefix = kFIRInstanceIDStoreKeyPrefix; + return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPrivate]; +} + +NSString *FIRInstanceIDPublicTagWithSubtype(NSString *subtype) { + static NSString *publicTag; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *mainAppBundleID = FIRInstanceIDAppIdentifier(); + publicTag = + [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPublicTagPrefix, mainAppBundleID]; + }); + return publicTag; +} + +NSString *FIRInstanceIDPrivateTagWithSubtype(NSString *subtype) { + static NSString *privateTag; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *mainAppBundleID = FIRInstanceIDAppIdentifier(); + privateTag = + [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPrivateTagPrefix, mainAppBundleID]; + }); + return privateTag; +} + +NSString *FIRInstanceIDCreationTimeKeyWithSubtype(NSString *subtype) { + return [NSString stringWithFormat:@"%@%@%@", subtype, kFIRInstanceIDStoreKeySubtype, + kFIRInstanceIDStoreKeyGenerationTime]; +} + +@interface FIRInstanceIDKeyPairStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair; +@property(nonatomic, readwrite, assign) NSInteger keychainEntitlementsErrorCount; + +@end + +@implementation FIRInstanceIDKeyPairStore + +- (instancetype)init { + self = [super init]; + if (self) { + NSString *fileName = [[self class] keyStoreFileName]; + _plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:fileName + subDirectory:kFIRInstanceIDSubDirectoryName]; + } + return self; +} + +- (BOOL)invalidateKeyPairsIfNeeded { + // Currently keypairs are always invalidated if self.plist is missing. This normally indicates + // a fresh install (or an uninstall/reinstall). In those situations the key pairs should be + // deleted. + // NOTE: Although this class refers to multiple key pairs, with different subtypes, in practice + // only a single subtype is currently supported. (b/64906549) + if (![self.plist doesFileExist]) { + // A fresh install, clear all the key pairs in the key chain. Do not perform migration as all + // key pairs are gone. + [self deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType handler:nil]; + return YES; + } + // Not a fresh install, perform migration at early state. + [self migrateKeyPairCacheIfNeededWithHandler:nil]; + return NO; +} + +- (BOOL)hasCachedKeyPairs { + NSError *error; + if ([self cachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:&error] == nil) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore000, + @"Failed to get the cached keyPair %@", error); + } + error = nil; + [self removeKeyPairCreationTimePlistWithError:&error]; + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore001, + @"Failed to remove keyPair creationTime plist %@", error); + } + return NO; + } + return YES; +} + +- (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error { + // Load the keyPair from Keychain (or generate a key pair, if this is the first run of the app). + FIRInstanceIDKeyPair *keyPair = [self loadKeyPairWithError:error]; + if (!keyPair) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair, + @"Keypair could not be loaded from Keychain. Error: %@", (*error)); + return nil; + } + + if (error) { + *error = nil; + } + NSString *appIdentity = FIRInstanceIDAppIdentity(keyPair); + if (!appIdentity.length) { + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + } + return appIdentity; +} + +- (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error { + // In case we call this from different threads we don't want to generate or fetch the + // keyPair multiple times. Once we have a keyPair in the cache it would mostly be used + // from there. + @synchronized(self) { + if ([self.keyPair isValid]) { + return self.keyPair; + } + + if (self.keychainEntitlementsErrorCount >= kMaxMissingEntitlementErrorCount) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore002, + @"Keychain not accessible, Entitlements missing error (-34018). " + @"Will not check token in cache."); + return nil; + } + + if (!self.keyPair) { + self.keyPair = [self validCachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:error]; + } + + if ((*error).code == kFIRInstanceIDSecMissingEntitlementErrorCode) { + self.keychainEntitlementsErrorCount++; + } + + if (!self.keyPair) { + self.keyPair = [self generateAndSaveKeyWithSubtype:kFIRInstanceIDKeyPairSubType + creationTime:FIRInstanceIDCurrentTimestampInSeconds() + error:error]; + } + } + return self.keyPair; +} + +// TODO(chliangGoogle: Remove subtype support, as it's not being used. +- (FIRInstanceIDKeyPair *)generateAndSaveKeyWithSubtype:(NSString *)subtype + creationTime:(int64_t)creationTime + error:(NSError **)error { + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype); + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype); + FIRInstanceIDKeyPair *keyPair = + [[FIRInstanceIDKeychain sharedInstance] generateKeyPairWithPrivateTag:privateKeyTag + publicTag:publicKeyTag]; + + if (![keyPair isValid]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore003, + @"Unable to generate keypair."); + return nil; + } + + NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype); + NSDictionary *keyPairData = @{creationTimeKey : @(creationTime)}; + + if (error) { + *error = nil; + } + NSMutableDictionary *allKeyPairs = [[self.plist contentAsDictionary] mutableCopy]; + if (allKeyPairs.count) { + [allKeyPairs addEntriesFromDictionary:keyPairData]; + } else { + allKeyPairs = [keyPairData mutableCopy]; + } + if (![self.plist writeDictionary:allKeyPairs error:error]) { + [FIRInstanceIDKeyPairStore deleteKeyPairWithPrivateTag:privateKeyTag + publicTag:publicKeyTag + handler:nil]; + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore004, + @"Failed to save keypair data to plist %@", error ? *error : @""); + return nil; + } + + return keyPair; +} + +- (FIRInstanceIDKeyPair *)validCachedKeyPairWithSubtype:(NSString *)subtype + error:(NSError **)error { + // On a new install (or if the ID was deleted), the plist will be missing, which should trigger + // a reset of the key pairs in Keychain (if they exist). + NSDictionary *allKeyPairs = [self.plist contentAsDictionary]; + NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype); + + if (allKeyPairs[creationTimeKey] > 0) { + return [self cachedKeyPairWithSubtype:subtype error:error]; + } else { + // There is no need to reset keypair again here as FIRInstanceID init call is always + // going to be ahead of this call, which already trigger keypair reset if it's new install + FIRInstanceIDErrorCode code = kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime; + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:code]; + } + return nil; + } +} + +- (FIRInstanceIDKeyPair *)cachedKeyPairWithSubtype:(NSString *)subtype + error:(NSError *__autoreleasing *)error { + // base64 encoded keys + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype); + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype); + return [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:privateKeyTag + publicKeyTag:publicKeyTag + error:error]; +} + ++ (FIRInstanceIDKeyPair *)keyPairForPrivateKeyTag:(NSString *)privateKeyTag + publicKeyTag:(NSString *)publicKeyTag + error:(NSError *__autoreleasing *)error { + _FIRInstanceIDDevAssert([privateKeyTag length] && [publicKeyTag length], + @"Invalid tags for keypair"); + if (![privateKeyTag length] || ![publicKeyTag length]) { + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPairTags]; + } + return nil; + } + + SecKeyRef privateKeyRef = FIRInstanceIDCachedKeyRefWithTag(privateKeyTag); + SecKeyRef publicKeyRef = FIRInstanceIDCachedKeyRefWithTag(publicKeyTag); + + if (!privateKeyRef || !publicKeyRef) { + if (error) { + *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeMissingKeyPair]; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPair000, + @"No keypair info is found with tag %@", privateKeyTag); + return nil; + } + + NSData *publicKeyData = FIRInstanceIDKeyDataWithTag(publicKeyTag); + NSData *privateKeyData = FIRInstanceIDKeyDataWithTag(privateKeyTag); + + FIRInstanceIDKeyPair *keyPair = [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKeyRef + publicKey:publicKeyRef + publicKeyData:publicKeyData + privateKeyData:privateKeyData]; + return keyPair; +} + +// Migrates from keypair saved under legacy keys (hardcoded value) to dynamic keys (stable, but +// unique for the app's bundle id +- (void)migrateKeyPairCacheIfNeededWithHandler:(void (^)(NSError *error))handler { + // Attempt to load keypair using legacy keys + NSString *legacyPublicKeyTag = + FIRInstanceIDLegacyPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType); + NSString *legacyPrivateKeyTag = + FIRInstanceIDLegacyPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType); + NSError *error; + FIRInstanceIDKeyPair *keyPair = + [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:legacyPrivateKeyTag + publicKeyTag:legacyPublicKeyTag + error:&error]; + if (![keyPair isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair, + @"There's no legacy keypair so no need to do migration."); + if (handler) { + handler(nil); + } + return; + } + + // Check whether migration already done. + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType); + if (FIRInstanceIDHasMigratedKeyPair(legacyPublicKeyTag, publicKeyTag)) { + if (handler) { + handler(nil); + } + return; + } + + // Also cache locally since we are sure to use the migrated key pair. + self.keyPair = keyPair; + + // Either new key pair doesn't exist or it's different than legacy key pair, start the migration. + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType); + [self updateKeyRef:keyPair.publicKey + withTag:publicKeyTag + handler:^(NSError *error) { + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairMigrationError, + @"Unable to migrate key pair from legacy ones."); + } + [self updateKeyRef:keyPair.privateKey + withTag:privateKeyTag + handler:^(NSError *error) { + if (error) { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeKeyPairMigrationError, + @"Unable to migrate key pair from legacy ones."); + return; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeKeyPairMigrationSuccess, + @"Successfully migrated the key pair from legacy ones."); + if (handler) { + handler(error); + } + }]; + }]; +} + +// Used for migrating from legacy tags to updated tags. The legacy keychain is not deleted for +// backward compatibility. +// TODO(chliangGoogle) Delete the legacy keychain when GCM is fully deprecated. +- (void)updateKeyRef:(SecKeyRef)keyRef + withTag:(NSString *)tag + handler:(void (^)(NSError *error))handler { + NSData *updatedTagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + // Always delete the old keychain before adding a new one to avoid conflicts. + NSDictionary *deleteQuery = @{ + (__bridge id)kSecAttrApplicationTag : updatedTagData, + (__bridge id)kSecClass : (__bridge id)kSecClassKey, + (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA, + (__bridge id)kSecReturnRef : @(YES), + }; + + [[FIRInstanceIDKeychain sharedInstance] + removeItemWithQuery:deleteQuery + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + NSDictionary *addQuery = @{ + (__bridge id)kSecAttrApplicationTag : updatedTagData, + (__bridge id)kSecClass : (__bridge id)kSecClassKey, + (__bridge id)kSecValueRef : (__bridge id)keyRef, + (__bridge id) + kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + [[FIRInstanceIDKeychain sharedInstance] addItemWithQuery:addQuery + handler:^(NSError *addError) { + if (handler) { + handler(addError); + } + }]; + }]; +} + +- (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype + handler:(void (^)(NSError *error))handler { + NSDictionary *allKeyPairs = [self.plist contentAsDictionary]; + + NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype); + NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype); + NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype); + + // remove the creation time + if (allKeyPairs[creationTimeKey] > 0) { + NSMutableDictionary *newKeyPairs = [NSMutableDictionary dictionaryWithDictionary:allKeyPairs]; + [newKeyPairs removeObjectForKey:creationTimeKey]; + + NSError *plistError; + if (![self.plist writeDictionary:newKeyPairs error:&plistError]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore006, + @"Unable to remove keypair creation time from plist %@", plistError); + } + } + + [FIRInstanceIDKeyPairStore + deleteKeyPairWithPrivateTag:privateKeyTag + publicTag:publicKeyTag + handler:^(NSError *error) { + // Delete legacy key pairs from GCM/FCM If they exist. All key pairs + // should be deleted when app is newly installed. + NSString *legacyPublicKeyTag = + FIRInstanceIDLegacyPublicTagWithSubtype(subtype); + NSString *legacyPrivateKeyTag = + FIRInstanceIDLegacyPrivateTagWithSubtype(subtype); + [FIRInstanceIDKeyPairStore + deleteKeyPairWithPrivateTag:legacyPrivateKeyTag + publicTag:legacyPublicKeyTag + handler:nil]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore007, + @"Unable to remove RSA keypair, error: %@", + error); + if (handler) { + handler(error); + } + } else { + self.keyPair = nil; + if (handler) { + handler(nil); + } + } + }]; +} + ++ (void)deleteKeyPairWithPrivateTag:(NSString *)privateTag + publicTag:(NSString *)publicTag + handler:(void (^)(NSError *))handler { + NSDictionary *queryPublicKey = FIRInstanceIDKeyPairQuery(publicTag, NO, NO); + NSDictionary *queryPrivateKey = FIRInstanceIDKeyPairQuery(privateTag, NO, NO); + + // Always remove public key first because it is the key we generate IID. + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:queryPublicKey + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + [[FIRInstanceIDKeychain sharedInstance] + removeItemWithQuery:queryPrivateKey + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + }]; +} + +- (BOOL)removeKeyPairCreationTimePlistWithError:(NSError *__autoreleasing *)error { + if (![self.plist deleteFile:error]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore008, + @"Unable to delete keypair creation times plist"); + return NO; + } + return YES; +} + ++ (NSString *)keyStoreFileName { + return kFIRInstanceIDKeyPairStoreFileName; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h new file mode 100644 index 0000000..b8baa6a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDKeyPair; + +/** + * A web-safe base64 encoded string with no padding. + * + * @param data The data to encode. + * + * @return A web-safe base 64 encoded string with no padding. + */ +FOUNDATION_EXPORT NSString *FIRInstanceIDWebSafeBase64(NSData *data); + +FOUNDATION_EXPORT NSData *FIRInstanceIDSHA1(NSData *data); + +FOUNDATION_EXPORT NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag, + BOOL addReturnAttr, + BOOL returnData); + +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m new file mode 100644 index 0000000..3298752 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m @@ -0,0 +1,84 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeyPairUtilities.h" + +#import + +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStringEncoding.h" + +NSString *FIRInstanceIDWebSafeBase64(NSData *data) { + // Websafe encoding with no padding. + FIRInstanceIDStringEncoding *encoding = + [FIRInstanceIDStringEncoding rfc4648Base64WebsafeStringEncoding]; + [encoding setDoPad:NO]; + return [encoding encode:data]; +} + +NSData *FIRInstanceIDSHA1(NSData *data) { + unsigned int outputLength = CC_SHA1_DIGEST_LENGTH; + unsigned char output[outputLength]; + unsigned int length = (unsigned int)[data length]; + + CC_SHA1(data.bytes, length, output); + return [NSMutableData dataWithBytes:output length:outputLength]; +} + +NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag, BOOL addReturnAttr, BOOL returnData) { + NSMutableDictionary *queryKey = [NSMutableDictionary dictionary]; + NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + queryKey[(__bridge id)kSecClass] = (__bridge id)kSecClassKey; + queryKey[(__bridge id)kSecAttrApplicationTag] = tagData; + queryKey[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA; + if (addReturnAttr) { + if (returnData) { + queryKey[(__bridge id)kSecReturnData] = @(YES); + } else { + queryKey[(__bridge id)kSecReturnRef] = @(YES); + } + } + return queryKey; +} + +NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair) { + // An Instance-ID is a 64 bit (8 byte) integer with a fixed 4-bit header of 0111 (=^ 0x7). + // The variable 60 bits are obtained by truncating the SHA1 of the app-instance's public key. + SecKeyRef publicKeyRef = [keyPair publicKey]; + if (!publicKeyRef) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPair002, + @"Unable to create a valid asymmetric crypto key"); + return nil; + } + NSData *publicKeyData = keyPair.publicKeyData; + NSData *publicKeySHA1 = FIRInstanceIDSHA1(publicKeyData); + + const uint8_t *bytes = publicKeySHA1.bytes; + NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1]; + + uint8_t b0 = bytes[0]; + // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0 + // and then adding 0x70 to it. + b0 = 0x70 + (0xF & b0); + // failsafe should give you back b0 itself + b0 = (b0 & 0xFF); + [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0]; + NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))]; + return FIRInstanceIDWebSafeBase64(data); +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h new file mode 100644 index 0000000..0bd2a49 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h @@ -0,0 +1,76 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/* The Keychain error domain */ +extern NSString *const kFIRInstanceIDKeychainErrorDomain; + +@class FIRInstanceIDKeyPair; + +/* + * Wrapping the keychain operations in a serialize queue. This is to avoid keychain operation + * blocking main queue. + */ +@interface FIRInstanceIDKeychain : NSObject + +/** + * FIRInstanceIDKeychain. + * + * @return A shared instance of FIRInstanceIDKeychain. + */ ++ (instancetype)sharedInstance; + +/** + * Get keychain items matching the given a query. + * + * @param keychainQuery The keychain query. + * + * @return An CFTypeRef result matching the provided inputs. + */ +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery; + +/** + * Remove the cached items from the keychain matching the query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the remove operation is + * complete, with an error if there is any. + */ +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *error))handler; + +/** + * Add the item with a given query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the add operation is + * complete, with an error if there is any. + */ +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler; + +#pragma mark - Keypair +/** + * Generate a public/private key pair given their tags. + * + * @param privateTag The private tag associated with the private key. + * @param publicTag The public tag associated with the public key. + * + * @return A new FIRInstanceIDKeyPair object. + */ +- (FIRInstanceIDKeyPair *)generateKeyPairWithPrivateTag:(NSString *)privateTag + publicTag:(NSString *)publicTag; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m new file mode 100644 index 0000000..81c7372 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m @@ -0,0 +1,174 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeychain.h" + +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDLogger.h" + +NSString *const kFIRInstanceIDKeychainErrorDomain = @"com.google.iid"; + +static const NSUInteger kRSA2048KeyPairSize = 2048; + +@interface FIRInstanceIDKeychain () { + dispatch_queue_t _keychainOperationQueue; +} + +@end + +@implementation FIRInstanceIDKeychain + ++ (instancetype)sharedInstance { + static FIRInstanceIDKeychain *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRInstanceIDKeychain alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _keychainOperationQueue = + dispatch_queue_create("com.google.FirebaseInstanceID.Keychain", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery { + __block SecKeyRef keyRef = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDKeychainReadItemError, + @"Info is not found in Keychain. OSStatus: %d. Keychain query: %@", + (int)status, keychainQuery); + } + }); + return keyRef; +} + +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery + handler:(void (^)(NSError *error))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery); + if (status != noErr) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDKeychainDeleteItemError, + @"Couldn't delete item from Keychain OSStatus: %d with the keychain query %@", + (int)status, keychainQuery); + } + + if (handler) { + NSError *error; + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); + + if (handler) { + NSError *error; + if (status != noErr) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainAddItemError, + @"Couldn't add item to Keychain OSStatus: %d", (int)status); + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (FIRInstanceIDKeyPair *)generateKeyPairWithPrivateTag:(NSString *)privateTag + publicTag:(NSString *)publicTag { + // TODO(chliangGoogle) this is called by appInstanceID, which is an internal API used by other + // Firebase teams, will see if we can make it async. + NSData *publicTagData = [publicTag dataUsingEncoding:NSUTF8StringEncoding]; + NSData *privateTagData = [privateTag dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary *privateKeyAttr = @{ + (__bridge id)kSecAttrIsPermanent : @YES, + (__bridge id)kSecAttrApplicationTag : privateTagData, + (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair Private Key", + (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + + NSDictionary *publicKeyAttr = @{ + (__bridge id)kSecAttrIsPermanent : @YES, + (__bridge id)kSecAttrApplicationTag : publicTagData, + (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair Public Key", + (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + + NSDictionary *keyPairAttributes = @{ + (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA, + (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair", + (__bridge id)kSecAttrKeySizeInBits : @(kRSA2048KeyPairSize), + (__bridge id)kSecPrivateKeyAttrs : privateKeyAttr, + (__bridge id)kSecPublicKeyAttrs : publicKeyAttr, + }; + + __block SecKeyRef privateKey = NULL; + __block SecKeyRef publicKey = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + // SecKeyGeneratePair does not allow you to set kSetAttrAccessible on the keys. We need the keys + // to be accessible even when the device is locked (i.e. app is woken up during a push + // notification, or some background refresh). + OSStatus status = + SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttributes, &publicKey, &privateKey); + if (status != noErr || publicKey == NULL || privateKey == NULL) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainCreateKeyPairError, + @"Couldn't create keypair from Keychain OSStatus: %d", + (int)status); + } + }); + // Extract the actual public and private key data from the Keychain + NSDictionary *publicKeyDataQuery = FIRInstanceIDKeyPairQuery(publicTag, YES, YES); + NSDictionary *privateKeyDataQuery = FIRInstanceIDKeyPairQuery(privateTag, YES, YES); + + NSData *publicKeyData = (__bridge NSData *)[self itemWithQuery:publicKeyDataQuery]; + NSData *privateKeyData = (__bridge NSData *)[self itemWithQuery:privateKeyDataQuery]; + + return [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKey + publicKey:publicKey + publicKeyData:publicKeyData + privateKeyData:privateKeyData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h new file mode 100644 index 0000000..ab93976 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRIMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRInstanceIDLoggerInfo + +// Convenience macros that log to the shared GTMLogger instance. These macros +// are how users should typically log to FIRInstanceIDLogger. +#define FIRInstanceIDLoggerDebug(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerInfo(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerNotice(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerWarning(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerError(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRInstanceIDLoggerInfo) + +@interface FIRInstanceIDLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared GTMLogger used exclusively + * for InstanceID log messages. + * @return the shared GTMLogger instance + */ +FIRInstanceIDLogger *FIRInstanceIDSharedLogger(void); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m new file mode 100644 index 0000000..2600d3b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDLogger.h" + +#import + +// Re-definition of FIRLogger service, as it is not included in :FIRAppHeaders target +NSString *const kFIRInstanceIDLoggerService = @"[Firebase/InstanceID]"; + +@implementation FIRInstanceIDLogger + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRInstanceIDMessageCode)messageCode { + return [NSString stringWithFormat:@"I-IID%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRInstanceIDLogger *FIRInstanceIDSharedLogger() { + static dispatch_once_t onceToken; + static FIRInstanceIDLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [[FIRInstanceIDLogger alloc] init]; + }); + + return logger; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h new file mode 100644 index 0000000..d1f2634 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h @@ -0,0 +1,183 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDCheckinStore; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDTokenStore; + +@class FIRInstanceIDStore; +@protocol FIRInstanceIDStoreDelegate + +/** + * This is called when the store has decided to invalide its tokens associated with the + * previous checkin credentials. After deleting the tokens locally, it calls this method + * to notify the delegate of the change. If possible, the delegate should use this time + * to request the invalidation of the tokens on the server as well. + */ +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +@end + +/** + * Used to persist the InstanceID tokens. This is also used to cache the Checkin + * credentials. The store also checks for stale entries in the store and + * let's us know if things in the store are stale or not. It does not however + * acts on stale entries in anyway. + */ +@interface FIRInstanceIDStore : NSObject + +/** + * The delegate set in the initializer which is notified of changes in the store. + */ +@property(nonatomic, readonly, weak) NSObject *delegate; + +- (instancetype)init __attribute__((unavailable("Use initWithDelegate: instead."))); + +/** + * Initialize a default store to persist InstanceID tokens and options. + * + * @param delegate The delegate with which to be notified of changes in the store. + * @return Store to persist InstanceID tokens. + */ +- (instancetype)initWithDelegate:(NSObject *)delegate; + +/** + * Initialize a store with the token store used to persist tokens, and a checkin store. + * Used for testing. + * + * @param checkinStore Persistent store that persists checkin preferences. + * @param tokenStore Persistent store that persists tokens. + * + * @return Store to persist InstanceID tokens and options. + */ +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Save +/** + * Save the instanceID token info to the store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo handler:(void (^)(NSError *))handler; + +#pragma mark - Get + +/** + * Get the cached token info. + * + * @param authorizedEntity The authorized entity for which we want the token. + * @param scope The scope for which we want the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * returns nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Delete + +/** + * Remove the cached token for a given authorizedEntity and scope. If the token was never + * cached or deleted from the cache before this is a no-op. + * + * @param authorizedEntity The authorizedEntity for the cached token. + * @param scope The scope for the cached token + */ +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Removes all cached tokens from the persistent store. In case deleting the cached tokens + * fails we try to delete the backup excluded plist that stores the tokens. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + * + */ +- (void)removeAllCachedTokensWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Persisting Checkin Preferences + +/** + * Save the checkin preferences + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(nullable void (^)(NSError *error))handler; + +/** + * Return the cached checkin preferences. + * + * @return Checkin preferences. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Remove the cached checkin preferences from the store. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Standard Directory sub-directory + +/** + * Check if supported directory has InstanceID subdirectory + * + * @return YES if the Application Support directory has InstanceID subdirectory else NO. + */ ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName; + +/** + * Create InstanceID subdirectory in Application support directory. + * + * @return YES if the subdirectory was created successfully else NO. + */ ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName; + +/** + * Removes Application Support subdirectory for InstanceID. + * + * @param error The error object if any while trying to delete the sub-directory. + * + * @return YES if the deletion was successful else NO. + */ ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m new file mode 100644 index 0000000..1c7a0d0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDStore.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinStore.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenStore.h" +#import "FIRInstanceIDVersionUtilities.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kCheckinFileName = @"g-checkin"; + +// APNS token (use the old key value i.e. with prefix GMS) +static NSString *const kFIRInstanceIDLibraryVersion = @"GMSInstanceID-version"; + +@interface FIRInstanceIDStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinStore *checkinStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore; + +@end + +@implementation FIRInstanceIDStore + +- (instancetype)initWithDelegate:(NSObject *)delegate { + FIRInstanceIDCheckinStore *checkinStore = [[FIRInstanceIDCheckinStore alloc] + initWithCheckinPlistFileName:kCheckinFileName + subDirectoryName:kFIRInstanceIDSubDirectoryName]; + + FIRInstanceIDTokenStore *tokenStore = [FIRInstanceIDTokenStore defaultStore]; + + return [self initWithCheckinStore:checkinStore tokenStore:tokenStore delegate:delegate]; +} + +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate { + self = [super init]; + if (self) { + _checkinStore = checkinStore; + _tokenStore = tokenStore; + _delegate = delegate; + [self resetCredentialsIfNeeded]; + } + return self; +} + +#pragma mark - Upgrades + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + ++ (NSString *)pathForSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[ dirPath, subDirectoryName ]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore000, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore001, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error { + if ([self hasSubDirectory:subDirectoryName]) { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return [[NSFileManager defaultManager] removeItemAtPath:subDirectoryPath error:error]; + } + } + return YES; +} + +/** + * Reset the keychain preferences if the app had been deleted earlier and then reinstalled. + * Keychain preferences are not cleared in the above scenario so explicitly clear them. + * + * In case of an iCloud backup and restore the Keychain preferences should already be empty + * since the Keychain items are marked with `*BackupThisDeviceOnly`. + */ +- (void)resetCredentialsIfNeeded { + BOOL checkinPlistExists = [self.checkinStore hasCheckinPlist]; + // Checkin info existed in backup excluded plist. Should not be a fresh install. + if (checkinPlistExists) { + // FCM user can still have the old version of checkin, migration should only happen once. + [self.checkinStore migrateCheckinItemIfNeeded]; + return; + } + + // reset checkin in keychain if a fresh install. + // set the old checkin preferences to unregister pre-registered tokens + FIRInstanceIDCheckinPreferences *oldCheckinPreferences = + [self.checkinStore cachedCheckinPreferences]; + + if (oldCheckinPreferences) { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeStore002, + @"Removed cached checkin preferences from Keychain because this is a fresh install."); + } else { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeStore003, + @"Couldn't remove cached checkin preferences for a fresh install. Error: %@", error); + } + if (oldCheckinPreferences.deviceID.length && oldCheckinPreferences.secretToken.length) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore006, + @"App reset detected. Will delete server registrations."); + // We don't really need to delete old FCM tokens created via IID auth tokens since + // those tokens are already hashed by APNS token as the has so creating a new + // token should automatically delete the old-token. + [self.delegate store:self didDeleteFCMScopedTokensForCheckin:oldCheckinPreferences]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore009, + @"App reset detected but no valid checkin auth preferences found." + @" Will not delete server registrations."); + } + }]; + } +} + +#pragma mark - Get + +- (FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + // TODO(chliangGoogle): If we don't have the token plist we should delete all the tokens from + // the keychain. This is because not having the plist signifies a backup and restore operation. + // In case the keychain has any tokens these would now be stale and therefore should be + // deleted. + if (![authorizedEntity length] || ![scope length]) { + return nil; + } + FIRInstanceIDTokenInfo *info = [self.tokenStore tokenInfoWithAuthorizedEntity:authorizedEntity + scope:scope]; + return info; +} + +- (NSArray *)cachedTokenInfos { + return [self.tokenStore cachedTokenInfos]; +} + +#pragma mark - Save + +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *error))handler { + [self.tokenStore saveTokenInfo:tokenInfo handler:handler]; +} + +#pragma mark - Delete + +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + if (![authorizedEntity length] || ![scope length]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore012, + @"Will not delete token with invalid entity: %@, scope: %@", + authorizedEntity, scope); + return; + } + [self.tokenStore removeTokenWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)removeAllCachedTokensWithHandler:(void (^)(NSError *error))handler { + [self.tokenStore removeAllTokensWithHandler:handler]; +} + +#pragma mark - FIRInstanceIDCheckinCache protocol + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + [self.checkinStore saveCheckinPreferences:preferences handler:handler]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.checkinStore cachedCheckinPreferences]; +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *))handler { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (handler) { + handler(error); + } + }]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h new file mode 100644 index 0000000..8f2f369 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h @@ -0,0 +1,66 @@ +// +// GTMStringEncoding.h +// +// Copyright 2010 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import + +// A generic class for arbitrary base-2 to 128 string encoding and decoding. +@interface FIRInstanceIDStringEncoding : NSObject { + @private + NSData *charMapData_; + char *charMap_; + int reverseCharMap_[128]; + int shift_; + unsigned int mask_; + BOOL doPad_; + char paddingChar_; + int padLen_; +} + ++ (id)rfc4648Base64WebsafeStringEncoding; + +// Create a new, autoreleased GTMStringEncoding object with the given string, +// as described below. ++ (id)stringEncodingWithString:(NSString *)string; + +// Initialize a new GTMStringEncoding object with the string. +// +// The length of the string must be a power of 2, at least 2 and at most 128. +// Only 7-bit ASCII characters are permitted in the string. +// +// These characters are the canonical set emitted during encoding. +// If the characters have alternatives (e.g. case, easily transposed) then use +// addDecodeSynonyms: to configure them. +- (id)initWithString:(NSString *)string; + +// Indicates whether padding is performed during encoding. +- (BOOL)doPad; +- (void)setDoPad:(BOOL)doPad; + +// Sets the padding character to use during encoding. +- (void)setPaddingChar:(char)c; + +// Encode a raw binary buffer to a 7-bit ASCII string. +- (NSString *)encode:(NSData *)data; + +// Decode a 7-bit ASCII string to a raw binary buffer. +- (NSData *)decode:(NSString *)string; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m new file mode 100644 index 0000000..64b6d3e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m @@ -0,0 +1,202 @@ +#import "FIRInstanceIDDefines.h" + +// +// FIRInstanceIDStringEncoding.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import "FIRInstanceIDStringEncoding.h" + +enum { kUnknownChar = -1, kPaddingChar = -2, kIgnoreChar = -3 }; + +@implementation FIRInstanceIDStringEncoding + ++ (id)rfc4648Base64WebsafeStringEncoding { + FIRInstanceIDStringEncoding *ret = [self + stringEncodingWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"]; + + [ret setPaddingChar:'=']; + [ret setDoPad:YES]; + return ret; +} + +static inline int lcm(int a, int b) { + for (int aa = a, bb = b;;) { + if (aa == bb) + return aa; + else if (aa < bb) + aa += a; + else + bb += b; + } +} + ++ (id)stringEncodingWithString:(NSString *)string { + return [[FIRInstanceIDStringEncoding alloc] initWithString:string]; +} + +- (id)initWithString:(NSString *)string { + if ((self = [super init])) { + charMapData_ = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (!charMapData_) { + // Unable to convert string to ASCII + return nil; + } + charMap_ = (char *)[charMapData_ bytes]; + NSUInteger length = [charMapData_ length]; + if (length < 2 || length > 128 || length & (length - 1)) { + // Length not a power of 2 between 2 and 128 + return nil; + } + + memset(reverseCharMap_, kUnknownChar, sizeof(reverseCharMap_)); + for (unsigned int i = 0; i < length; i++) { + if (reverseCharMap_[(int)charMap_[i]] != kUnknownChar) { + // Duplicate character at |i| + return nil; + } + reverseCharMap_[(int)charMap_[i]] = i; + } + + for (NSUInteger i = 1; i < length; i <<= 1) shift_++; + mask_ = (1 << shift_) - 1; + padLen_ = lcm(8, shift_) / shift_; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"", 1 << shift_, charMapData_]; +} + +- (BOOL)doPad { + return doPad_; +} + +- (void)setDoPad:(BOOL)doPad { + doPad_ = doPad; +} + +- (void)setPaddingChar:(char)c { + paddingChar_ = c; + reverseCharMap_[(int)c] = kPaddingChar; +} + +- (NSString *)encode:(NSData *)inData { + NSUInteger inLen = [inData length]; + if (inLen <= 0) { + // Empty input + return @""; + } + unsigned char *inBuf = (unsigned char *)[inData bytes]; + NSUInteger inPos = 0; + + NSUInteger outLen = (inLen * 8 + shift_ - 1) / shift_; + if (doPad_) { + outLen = ((outLen + padLen_ - 1) / padLen_) * padLen_; + } + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + unsigned int buffer = inBuf[inPos++]; + int bitsLeft = 8; + while (bitsLeft > 0 || inPos < inLen) { + if (bitsLeft < shift_) { + if (inPos < inLen) { + buffer <<= 8; + buffer |= (inBuf[inPos++] & 0xff); + bitsLeft += 8; + } else { + int pad = shift_ - bitsLeft; + buffer <<= pad; + bitsLeft += pad; + } + } + unsigned int idx = (buffer >> (bitsLeft - shift_)) & mask_; + bitsLeft -= shift_; + outBuf[outPos++] = charMap_[idx]; + } + + if (doPad_) { + while (outPos < outLen) outBuf[outPos++] = paddingChar_; + } + + _FIRInstanceIDDevAssert(outPos == outLen, @"Underflowed output buffer"); + [outData setLength:outPos]; + + return [[NSString alloc] initWithData:outData encoding:NSASCIIStringEncoding]; +} + +- (NSData *)decode:(NSString *)inString { + char *inBuf = (char *)[inString cStringUsingEncoding:NSASCIIStringEncoding]; + if (!inBuf) { + // Unable to convert buffer to ASCII + return nil; + } + NSUInteger inLen = strlen(inBuf); + + NSUInteger outLen = inLen * shift_ / 8; + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + int buffer = 0; + int bitsLeft = 0; + BOOL expectPad = NO; + for (NSUInteger i = 0; i < inLen; i++) { + int val = reverseCharMap_[(int)inBuf[i]]; + switch (val) { + case kIgnoreChar: + break; + case kPaddingChar: + expectPad = YES; + break; + case kUnknownChar: + // Unexpected data at input pos |i| + return nil; + default: + if (expectPad) { + // Expected further padding characters + return nil; + } + buffer <<= shift_; + buffer |= val & mask_; + bitsLeft += shift_; + if (bitsLeft >= 8) { + outBuf[outPos++] = (unsigned char)(buffer >> (bitsLeft - 8)); + bitsLeft -= 8; + } + break; + } + } + + if (bitsLeft && buffer & ((1 << bitsLeft) - 1)) { + // Incomplete trailing data + return nil; + } + + // Shorten buffer if needed due to padding chars + _FIRInstanceIDDevAssert(outPos <= outLen, @"Overflowed buffer"); + [outData setLength:outPos]; + + return outData; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h new file mode 100644 index 0000000..58368d0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenDeleteOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(nullable NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(nullable FIRInstanceIDKeyPair *)keyPair + action:(FIRInstanceIDTokenAction)action; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m new file mode 100644 index 0000000..365f321 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m @@ -0,0 +1,120 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenDeleteOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +@implementation FIRInstanceIDTokenDeleteOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair + action:(FIRInstanceIDTokenAction)action { + self = [super initWithAction:action + forAuthorizedEntity:authorizedEntity + scope:scope + options:nil + checkinPreferences:checkinPreferences + keyPair:keyPair]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + NSMutableURLRequest *request = [FIRInstanceIDTokenOperation requestWithAuthHeader:authHeader]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [FIRInstanceIDTokenOperation standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"delete" value:@"true"]]; + if (self.action == FIRInstanceIDTokenActionDeleteTokenAndIID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"iid-operation" + value:@"delete"]]; + } + if (self.authorizedEntity) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + } + // Typically we include our public key-signed url items, but in some cases (like deleting all FCM + // tokens), we don't. + if (self.keyPair != nil) { + [queryItems addObjectsFromArray:[self queryItemsWithKeyPair:self.keyPair]]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest, + @"Unregister request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError, + @"Device unregister HTTP fetch error. Error code: %ld", + _FIRInstanceID_L(error.code)); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + if (![dataResponse hasPrefix:@"deleted="] && ![dataResponse hasPrefix:@"token="]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse, + @"Invalid unregister response %@", response); + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded token:nil error:nil]; +} +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h new file mode 100644 index 0000000..87be60f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseUserAgentKey; + +@interface FIRInstanceIDTokenFetchOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair; + +@end +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m new file mode 100644 index 0000000..b545c24 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m @@ -0,0 +1,205 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenFetchOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +#import + +// We can have a static int since this error should theoretically only +// happen once (for the first time). If it repeats there is something +// else that is wrong. +static int phoneRegistrationErrorRetryCount = 0; +static const int kMaxPhoneRegistrationErrorRetryCount = 10; +NSString *const kFIRInstanceIDFirebaseUserAgentKey = @"X-firebase-client"; + +@implementation FIRInstanceIDTokenFetchOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair { + self = [super initWithAction:FIRInstanceIDTokenActionFetch + forAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + keyPair:keyPair]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + NSMutableURLRequest *request = [[self class] requestWithAuthHeader:authHeader]; + NSString *checkinVersionInfo = self.checkinPreferences.versionInfo; + [request setValue:checkinVersionInfo forHTTPHeaderField:@"info"]; + [request setValue:[FIRApp firebaseUserAgent] + forHTTPHeaderField:kFIRInstanceIDFirebaseUserAgentKey]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [[self class] standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-subtype" + value:self.authorizedEntity]]; + + [queryItems addObjectsFromArray:[self queryItemsWithKeyPair:self.keyPair]]; + + // Create query items from passed-in options + id apnsTokenData = self.options[kFIRInstanceIDTokenOptionsAPNSKey]; + id apnsSandboxValue = self.options[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if ([apnsTokenData isKindOfClass:[NSData class]] && + [apnsSandboxValue isKindOfClass:[NSNumber class]]) { + NSString *APNSString = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + apnsTokenData, ((NSNumber *)apnsSandboxValue).boolValue); + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsAPNSKey + value:APNSString]; + [queryItems addObject:item]; + } + id firebaseAppID = self.options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + if ([firebaseAppID isKindOfClass:[NSString class]]) { + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsFirebaseAppIDKey + value:(NSString *)firebaseAppID]; + [queryItems addObject:item]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest, + @"Register request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +#pragma mark - Request Handling + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationRequestError, + @"Token fetch HTTP error. Error Code: %ld", (long)error.code); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSDictionary *parsedResponse = [self parseFetchTokenResponse:dataResponse]; + _FIRInstanceIDDevAssert(parsedResponse.count, @"Invalid registration response"); + + if ([parsedResponse[@"token"] length]) { + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded + token:parsedResponse[@"token"] + error:nil]; + return; + } + + NSString *errorValue = parsedResponse[@"Error"]; + NSError *responseError; + if (errorValue.length) { + NSArray *errorComponents = [errorValue componentsSeparatedByString:@":"]; + // HACK (Kansas replication delay), PHONE_REGISTRATION_ERROR on App + // uninstall and reinstall. + if ([errorComponents containsObject:@"PHONE_REGISTRATION_ERROR"]) { + // Encountered issue http://b/27043795 + // Retry register until successful or another error encountered or a + // certain number of tries are over. + + if (phoneRegistrationErrorRetryCount < kMaxPhoneRegistrationErrorRetryCount) { + const int nextRetryInterval = 1 << phoneRegistrationErrorRetryCount; + FIRInstanceID_WEAKIFY(self); + + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(nextRetryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + phoneRegistrationErrorRetryCount++; + [self performTokenOperation]; + }); + return; + } + } else if ([errorComponents containsObject:kFIRInstanceID_CMD_RST]) { + // Server detected the identity we use is no longer valid. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:kFIRInstanceIDIdentityInvalidatedNotification object:nil]; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal001, + @"Identity is invalid. Server request identity reset."); + responseError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidIdentity]; + } + } + if (!responseError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse, + @"Invalid fetch response, expected 'token' or 'Error' key"); + responseError = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:responseError]; +} + +// expect a response e.g. "token=\nGOOG.ttl=123" +- (NSDictionary *)parseFetchTokenResponse:(NSString *)response { + NSArray *lines = [response componentsSeparatedByString:@"\n"]; + NSMutableDictionary *parsedResponse = [NSMutableDictionary dictionary]; + for (NSString *line in lines) { + NSArray *keyAndValue = [line componentsSeparatedByString:@"="]; + if ([keyAndValue count] > 1) { + parsedResponse[keyAndValue[0]] = keyAndValue[1]; + } + } + return parsedResponse; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h new file mode 100644 index 0000000..34ad716 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h @@ -0,0 +1,82 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstanceIDAPNSInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an Instance ID token, and all of the relevant information + * associated with it. It can read from and write to an NSDictionary object, for + * simple serialization. + */ +@interface FIRInstanceIDTokenInfo : NSObject + +/// The authorized entity (also known as Sender ID), associated with the token. +@property(nonatomic, readonly, copy) NSString *authorizedEntity; +/// The scope associated with the token. This is an arbitrary string, typically "*". +@property(nonatomic, readonly, copy) NSString *scope; +/// The token value itself, with which all other properties are associated. +@property(nonatomic, readonly, copy) NSString *token; + +// These properties are nullable because they might not exist for tokens fetched from +// legacy storage formats. + +/// The app version that this token represents. +@property(nonatomic, readonly, copy, nullable) NSString *appVersion; +/// The Firebase app ID (also known as GMP App ID), that this token is associated with. +@property(nonatomic, readonly, copy, nullable) NSString *firebaseAppID; + +/// Tokens may not always be associated with an APNs token, and may be associated after +/// being created. +@property(nonatomic, strong, nullable) FIRInstanceIDAPNSInfo *APNSInfo; +/// The time that this token info was updated. The cache time is writeable, since in +/// some cases the token info may be refreshed from the server. In those situations, +/// the cacheTime would be updated. +@property(nonatomic, copy, nullable) NSDate *cacheTime; + +/** + * Initializes a FIRInstanceIDTokenInfo object with the required parameters. These + * parameters represent all the relevant associated data with a token. + * + * @param authorizedEntity The authorized entity (also known as Sender ID). + * @param scope The scope of the token, typically "*" meaning + * it's a "default scope". + * @param token The token value itself. + * @param appVersion The application version that this token is associated with. + * @param firebaseAppID The Firebase app ID which this token is associated with. + * @return An instance of FIRInstanceIDTokenInfo. + */ +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(nullable NSString *)appVersion + firebaseAppID:(nullable NSString *)firebaseAppID; + +/** + * Check whether the token is still fresh based on: + * 1. Last fetch token is within the 7 days. + * 2. Language setting is not changed. + * 3. App version is current. + * 4. GMP App ID is current. + */ +- (BOOL)isFresh; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m new file mode 100644 index 0000000..a4d284b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m @@ -0,0 +1,188 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenInfo.h" + +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" + +/** + * @enum Token Info Dictionary Key Constants + * @discussion The keys that are checked when a token info is + * created from a dictionary. The same keys are used + * when decoding/encoding an archive. + */ +/// Specifies a dictonary key whose value represents the authorized entity, or +/// Sender ID for the token. +static NSString *const kFIRInstanceIDAuthorizedEntityKey = @"authorized_entity"; +/// Specifies a dictionary key whose value represents the scope of the token, +/// typically "*". +static NSString *const kFIRInstanceIDScopeKey = @"scope"; +/// Specifies a dictionary key which represents the token value itself. +static NSString *const kFIRInstanceIDTokenKey = @"token"; +/// Specifies a dictionary key which represents the app version associated +/// with the token. +static NSString *const kFIRInstanceIDAppVersionKey = @"app_version"; +/// Specifies a dictionary key which represents the GMP App ID associated with +/// the token. +static NSString *const kFIRInstanceIDFirebaseAppIDKey = @"firebase_app_id"; +/// Specifies a dictionary key representing an archive for a +/// `FIRInstanceIDAPNSInfo` object. +static NSString *const kFIRInstanceIDAPNSInfoKey = @"apns_info"; +/// Specifies a dictionary key representing the "last cached" time for the token. +static NSString *const kFIRInstanceIDCacheTimeKey = @"cache_time"; +/// Default interval that token stays fresh. +const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60; // 7 days. + +@implementation FIRInstanceIDTokenInfo + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(NSString *)appVersion + firebaseAppID:(NSString *)firebaseAppID { + self = [super init]; + if (self) { + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _token = [token copy]; + _appVersion = [appVersion copy]; + _firebaseAppID = [firebaseAppID copy]; + } + return self; +} + +- (BOOL)isFresh { + // Last fetch token cache time could be null if token is from legacy storage format. Then token is + // considered not fresh and should be refreshed and overwrite with the latest storage format. + if (!_cacheTime) { + return NO; + } + + // Check if app has just been updated to a new version. + NSString *currentAppVersion = FIRInstanceIDCurrentAppVersion(); + if (!_appVersion || ![_appVersion isEqualToString:currentAppVersion]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager004, + @"Invalidating cached token for %@ (%@) due to app version change.", + _authorizedEntity, _scope); + return NO; + } + + // Check if GMP App ID has changed + NSString *currentFirebaseAppID = FIRInstanceIDFirebaseAppID(); + if (!_firebaseAppID || ![_firebaseAppID isEqualToString:currentFirebaseAppID]) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged, + @"Invalidating cached token due to Firebase App IID change from %@ to %@", _firebaseAppID, + currentFirebaseAppID); + return NO; + } + + // Check whether locale has changed, if yes, token needs to be updated with server for locale + // information. + if (FIRInstanceIDHasLocaleChanged()) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenInfoLocaleChanged, + @"Invalidating cached token due to locale change"); + return NO; + } + + // Locale is not changed, check whether token has been fetched within 7 days. + NSTimeInterval lastFetchTokenTimestamp = [_cacheTime timeIntervalSince1970]; + NSTimeInterval currentTimestamp = FIRInstanceIDCurrentTimestampInSeconds(); + NSTimeInterval timeSinceLastFetchToken = currentTimestamp - lastFetchTokenTimestamp; + return (timeSinceLastFetchToken < kDefaultFetchTokenInterval); +} +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + // These value cannot be nil + + id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey]; + if (![authorizedEntity isKindOfClass:[NSString class]]) { + return nil; + } + + id scope = [aDecoder decodeObjectForKey:kFIRInstanceIDScopeKey]; + if (![scope isKindOfClass:[NSString class]]) { + return nil; + } + + id token = [aDecoder decodeObjectForKey:kFIRInstanceIDTokenKey]; + if (![token isKindOfClass:[NSString class]]) { + return nil; + } + + // These values are nullable, so only fail the decode if the type does not match + + id appVersion = [aDecoder decodeObjectForKey:kFIRInstanceIDAppVersionKey]; + if (appVersion && ![appVersion isKindOfClass:[NSString class]]) { + return nil; + } + + id firebaseAppID = [aDecoder decodeObjectForKey:kFIRInstanceIDFirebaseAppIDKey]; + if (firebaseAppID && ![firebaseAppID isKindOfClass:[NSString class]]) { + return nil; + } + + id rawAPNSInfo = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoKey]; + if (rawAPNSInfo && ![rawAPNSInfo isKindOfClass:[NSData class]]) { + return nil; + } + + FIRInstanceIDAPNSInfo *APNSInfo = nil; + if (rawAPNSInfo) { + @try { + APNSInfo = [NSKeyedUnarchiver unarchiveObjectWithData:rawAPNSInfo]; + } @catch (NSException *exception) { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo, + @"Could not parse raw APNS Info while parsing archived token info."); + APNSInfo = nil; + } @finally { + } + } + + id cacheTime = [aDecoder decodeObjectForKey:kFIRInstanceIDCacheTimeKey]; + if (cacheTime && ![cacheTime isKindOfClass:[NSDate class]]) { + return nil; + } + + self = [super init]; + if (self) { + _authorizedEntity = authorizedEntity; + _scope = scope; + _token = token; + _appVersion = appVersion; + _firebaseAppID = firebaseAppID; + _APNSInfo = APNSInfo; + _cacheTime = cacheTime; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.authorizedEntity forKey:kFIRInstanceIDAuthorizedEntityKey]; + [aCoder encodeObject:self.scope forKey:kFIRInstanceIDScopeKey]; + [aCoder encodeObject:self.token forKey:kFIRInstanceIDTokenKey]; + [aCoder encodeObject:self.appVersion forKey:kFIRInstanceIDAppVersionKey]; + [aCoder encodeObject:self.firebaseAppID forKey:kFIRInstanceIDFirebaseAppIDKey]; + if (self.APNSInfo) { + NSData *rawAPNSInfo = [NSKeyedArchiver archivedDataWithRootObject:self.APNSInfo]; + [aCoder encodeObject:rawAPNSInfo forKey:kFIRInstanceIDAPNSInfoKey]; + } + [aCoder encodeObject:self.cacheTime forKey:kFIRInstanceIDCacheTimeKey]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h new file mode 100644 index 0000000..491b99c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +@class FIRInstanceIDAuthService; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDKeyPair; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDStore; + +typedef NS_OPTIONS(NSUInteger, FIRInstanceIDInvalidTokenReason) { + FIRInstanceIDInvalidTokenReasonNone = 0, // 0 + FIRInstanceIDInvalidTokenReasonAppVersion = (1 << 0), // 0...00001 + FIRInstanceIDInvalidTokenReasonAPNSToken = (1 << 1), // 0...00010 +}; + +/** + * Manager for the InstanceID token requests i.e `newToken` and `deleteToken`. This + * manages the overall interaction of the `InstanceIDStore`, the token register + * service and the callbacks associated with `GCMInstanceID`. + */ +@interface FIRInstanceIDTokenManager : NSObject + +/// Expose the auth service, so it can be used by others +@property(nonatomic, readonly, strong) FIRInstanceIDAuthService *authService; + +/** + * Fetch new token for the given authorizedEntity and scope. This makes an + * asynchronous request to the InstanceID backend to create a new token for + * the service and returns it. This will replace any old token for the given + * authorizedEntity and scope that has been cached before. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param keyPair The keyPair that represents the app identity. + * @param options The options to be added to the fetch request. + * @param handler The handler to be invoked once we have the token or the + * fetch request to InstanceID backend results in an error. Also + * since it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Return the cached token info, if one exists, for the given authorizedEntity and scope. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info, if available, matching the parameters. + */ +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Delete the token for the given authorizedEntity and scope. If the token has + * been cached, it will be deleted from the store. It will also make an + * asynchronous request to the InstanceID backend to invalidate the token. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param keyPair The keyPair that represents the app identity. + * @param handler The handler to be invoked once the delete request to + * InstanceID backend has returned. If the request was + * successful we invoke the handler with a nil error; + * otherwise we call it with an appropriate error. Also since + * it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. This method should only be triggered + * when InstanceID is deleted + * + * @param keyPair The keyPair for the given app. + * @param handler The handler to be invoked once the delete request to InstanceID backend + * has returned. If the request was successful we invoke the handler with + * a nil error; else we pass in an appropriate error. This should be non-nil + * and be called asynchronously. + */ +- (void)deleteAllTokensWithKeyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler; + +/** + * Stop any ongoing token operations. + */ +- (void)stopAllTokenOperations; + +#pragma mark - Invalidating Cached Tokens + +/** + * Invalidate any cached tokens, if the app version has changed since last launch or if the token + * is cached for more than 7 days. + * + * @return Whether we should fetch default token from server. + * + * @discussion This should safely be called prior to any tokens being retrieved from + * the cache or being fetched from the network. + */ +- (BOOL)checkForTokenRefreshPolicy; + +/** + * Upon being provided with different APNs or sandbox, any locally cached tokens + * should be deleted, and the new APNs token should be cached. + * + * @discussion It is possible for this method to be called while token operations are + * in-progress or queued. In this case, the in-flight token operations will have stale + * APNs information. The default token is checked for being out-of-date by Instance ID, + * and re-fetched. Custom tokens are not currently checked. + * + * @param deviceToken The APNS device token, provided by the operating system. + * @param isSandbox YES if the device token is for the sandbox environment, NO otherwise. + * + * @return The array of FIRInstanceIDTokenInfo objects which were invalidated. + */ +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m new file mode 100644 index 0000000..0c4f644 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m @@ -0,0 +1,341 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenManager.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenDeleteOperation.h" +#import "FIRInstanceIDTokenFetchOperation.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenOperation.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDTokenManager () + +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *instanceIDStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthService *authService; +@property(nonatomic, readonly, strong) NSOperationQueue *tokenOperations; + +@property(nonatomic, readwrite, strong) FIRInstanceIDAPNSInfo *currentAPNSInfo; + +@end + +@implementation FIRInstanceIDTokenManager + +- (instancetype)init { + self = [super init]; + if (self) { + _instanceIDStore = [[FIRInstanceIDStore alloc] initWithDelegate:self]; + _authService = [[FIRInstanceIDAuthService alloc] initWithStore:_instanceIDStore]; + [self configureTokenOperations]; + } + return self; +} + +- (void)dealloc { + [self stopAllTokenOperations]; +} + +- (void)configureTokenOperations { + _tokenOperations = [[NSOperationQueue alloc] init]; + _tokenOperations.name = @"com.google.iid-token-operations"; + // For now, restrict the operations to be serial, because in some cases (like if the + // authorized entity and scope are the same), order matters. + // If we have to deal with several different token requests simultaneously, it would be a good + // idea to add some better intelligence around this (performing unrelated token operations + // simultaneously, etc.). + _tokenOperations.maxConcurrentOperationCount = 1; + if ([_tokenOperations respondsToSelector:@selector(qualityOfService)]) { + _tokenOperations.qualityOfService = NSOperationQualityOfServiceUtility; + } +} + +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager000, + @"Fetch new token for authorizedEntity: %@, scope: %@", authorizedEntity, + scope); + FIRInstanceIDTokenFetchOperation *operation = + [self createFetchOperationWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + keyPair:keyPair]; + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenOperationCompletion completion = + ^(FIRInstanceIDTokenOperationResult result, NSString *_Nullable token, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + handler(nil, error); + return; + } + NSString *firebaseAppID = options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + FIRInstanceIDTokenInfo *tokenInfo = [[FIRInstanceIDTokenInfo alloc] + initWithAuthorizedEntity:authorizedEntity + scope:scope + token:token + appVersion:FIRInstanceIDCurrentAppVersion() + firebaseAppID:firebaseAppID]; + tokenInfo.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:options]; + + [self.instanceIDStore + saveTokenInfo:tokenInfo + handler:^(NSError *error) { + if (!error) { + // Do not send the token back in case the save was unsuccessful. Since with + // the new asychronous fetch mechanism this can lead to infinite loops, for + // example, we will return a valid token even though we weren't able to store + // it in our cache. The first token will lead to a onTokenRefresh callback + // wherein the user again calls `getToken` but since we weren't able to save + // it we won't hit the cache but hit the server again leading to an infinite + // loop. + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManager001, + @"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@", + token, authorizedEntity, scope); + + if (handler) { + handler(token, nil); + } + } else { + if (handler) { + handler(nil, error); + } + } + }]; + }; + // Add completion handler, and ensure it's called on the main queue + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(result, token, error); + }); + }]; + [self.tokenOperations addOperation:operation]; +} + +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + return [self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + keyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if ([self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:authorizedEntity scope:scope]; + } + // Does not matter if we cannot find it in the cache. Still make an effort to unregister + // from the server. + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + keyPair:keyPair + action:FIRInstanceIDTokenActionDeleteToken]; + + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensWithKeyPair:(FIRInstanceIDKeyPair *)keyPair + handler:(FIRInstanceIDDeleteHandler)handler { + // delete all tokens + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + if (!checkinPreferences) { + // The checkin is already deleted. No need to trigger the token delete operation as client no + // longer has the checkin information for server to delete. + dispatch_async(dispatch_get_main_queue(), ^{ + handler(nil); + }); + return; + } + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:kFIRInstanceIDKeychainWildcardIdentifier + scope:kFIRInstanceIDKeychainWildcardIdentifier + checkinPreferences:checkinPreferences + keyPair:keyPair + action:FIRInstanceIDTokenActionDeleteTokenAndIID]; + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler { + [self.instanceIDStore removeAllCachedTokensWithHandler:handler]; +} + +- (void)stopAllTokenOperations { + [self.authService stopCheckinRequest]; + [self.tokenOperations cancelAllOperations]; +} + +#pragma mark - FIRInstanceIDStoreDelegate + +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + // Make a best effort try to delete the old client related state on the FCM server. This is + // required to delete old pubusb registrations which weren't cleared when the app was deleted. + // + // This is only a one time effort. If this call fails the client would still receive duplicate + // pubsub notifications if he is again subscribed to the same topic. + // + // The client state should be cleared on the server for the provided checkin preferences. + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:nil + scope:nil + checkinPreferences:checkin + keyPair:nil + action:FIRInstanceIDTokenActionDeleteToken]; + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + FIRInstanceIDMessageCode code = + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset; + FIRInstanceIDLoggerDebug(code, @"Failed to delete GCM server registrations on app reset."); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset, + @"Successfully deleted GCM server registrations on app reset"); + } + }]; + + [self.tokenOperations addOperation:operation]; +} + +#pragma mark - Unit Testing Stub Helpers +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenFetchOperation *) + createFetchOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + keyPair:(FIRInstanceIDKeyPair *)keyPair { + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenFetchOperation *operation = + [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + keyPair:keyPair]; + return operation; +} + +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenDeleteOperation *) + createDeleteOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair + action:(FIRInstanceIDTokenAction)action { + FIRInstanceIDTokenDeleteOperation *operation = + [[FIRInstanceIDTokenDeleteOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + keyPair:keyPair + action:action]; + return operation; +} + +#pragma mark - Invalidating Cached Tokens +- (BOOL)checkForTokenRefreshPolicy { + // We know at least one cached token exists. + BOOL shouldFetchDefaultToken = NO; + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *tokenInfo in tokenInfos) { + BOOL isTokenFresh = [tokenInfo isFresh]; + if (isTokenFresh) { + // Token is fresh, do nothing. + continue; + } + if ([tokenInfo.scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + // Default token is expired, do not mark for deletion. Fetch directly from server to + // replace the current one. + shouldFetchDefaultToken = YES; + } else { + // Non-default token is expired, mark for deletion. + [tokenInfosToDelete addObject:tokenInfo]; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken, + @"Invalidating cached token for %@ (%@) due to token is no longer fresh.", + tokenInfo.authorizedEntity, tokenInfo.scope); + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return shouldFetchDefaultToken; +} + +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox { + // Each cached IID token that is missing an APNSInfo, or has an APNSInfo associated should be + // checked and invalidated if needed. + FIRInstanceIDAPNSInfo *APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:deviceToken + isSandbox:isSandbox]; + if ([self.currentAPNSInfo isEqualToAPNSInfo:APNSInfo]) { + return @[]; + } + self.currentAPNSInfo = APNSInfo; + + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *cachedTokenInfo in tokenInfos) { + // Check if the cached APNSInfo is nil, or if it is an old APNSInfo. + if (!cachedTokenInfo.APNSInfo || + ![cachedTokenInfo.APNSInfo isEqualToAPNSInfo:self.currentAPNSInfo]) { + // Mark for invalidation. + [tokenInfosToDelete addObject:cachedTokenInfo]; + } + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated, + @"Invalidating cached token for %@ (%@) due to APNs token change.", + tokenInfoToDelete.authorizedEntity, tokenInfoToDelete.scope); + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return tokenInfosToDelete; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h new file mode 100644 index 0000000..68d9db1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h @@ -0,0 +1,67 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDUtilities.h" + +@class FIRInstanceIDKeyPair; +@class FIRInstanceIDURLQueryItem; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenOperation (Private) + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + ++ (NSURLSession *)sharedURLSession; + +#pragma mark - Initialization +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair; + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString; ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope; +- (NSArray *)queryItemsWithKeyPair:(FIRInstanceIDKeyPair *)keyPair; + +#pragma mark - HTTP Headers +/** + * Given a valid checkin preferences object, it will return a string that can be used + * in the "Authorization" HTTP header to authenticate this request. + * + * @param checkin The valid checkin preferences object, with a deviceID and secretToken. + */ ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +#pragma mark - Result +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h new file mode 100644 index 0000000..1a1842c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDKeyPair; +@class FIRInstanceIDCheckinPreferences; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on an FCM token. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenAction) { + FIRInstanceIDTokenActionFetch, + FIRInstanceIDTokenActionDeleteToken, + FIRInstanceIDTokenActionDeleteTokenAndIID, +}; + +/** + * Represents the possible results of a token operation. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenOperationResult) { + FIRInstanceIDTokenOperationSucceeded, + FIRInstanceIDTokenOperationError, + FIRInstanceIDTokenOperationCancelled, +}; + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param result The result of the operation. + * @param token If the action for fetching a token and the request was successful, this will hold + * the value of the token. Otherwise nil. + * @param error The error which occurred while performing the token operation. This will be nil + * in case the operation was successful, or if the operation was cancelled. + */ +typedef void (^FIRInstanceIDTokenOperationCompletion)(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, + NSError *_Nullable error); + +@interface FIRInstanceIDTokenOperation : NSOperation + +@property(nonatomic, readonly) FIRInstanceIDTokenAction action; +@property(nonatomic, readonly, nullable) NSString *authorizedEntity; +@property(nonatomic, readonly, nullable) NSString *scope; +@property(nonatomic, readonly, nullable) NSDictionary *options; +@property(nonatomic, readonly, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readonly, strong) FIRInstanceIDKeyPair *keyPair; + +@property(nonatomic, readonly) FIRInstanceIDTokenOperationResult result; + +- (instancetype)init NS_UNAVAILABLE; + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m new file mode 100644 index 0000000..dcfdb84 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m @@ -0,0 +1,243 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDKeyPair.h" +#import "FIRInstanceIDKeyPairUtilities.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2; + +static NSString *const kFIRInstanceIDParamInstanceID = @"appid"; +// Scope parameter that defines the service using the token +static NSString *const kFIRInstanceIDParamScope = @"X-scope"; +// Defines the SDK version +static NSString *const kFIRInstanceIDParamFCMLibVersion = @"X-cliv"; + +@interface FIRInstanceIDTokenOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + +@end + +@implementation FIRInstanceIDTokenOperation + ++ (NSURLSession *)sharedURLSession { + static NSURLSession *tokenOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + tokenOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + tokenOperationSharedSession.sessionDescription = @"com.google.iid.tokens.session"; + }); + return tokenOperationSharedSession; +} + +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + keyPair:(FIRInstanceIDKeyPair *)keyPair { + self = [super init]; + if (self) { + _action = action; + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _options = [options copy]; + _checkinPreferences = checkinPreferences; + _keyPair = keyPair; + _completionHandlers = [NSMutableArray array]; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _testBlock = nil; + _authorizedEntity = nil; + _scope = nil; + _options = nil; + _checkinPreferences = nil; + _keyPair = nil; + [_completionHandlers removeAllObjects]; + _completionHandlers = nil; +} + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler { + [self.completionHandlers addObject:handler]; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; + return; + } + + // Quickly validate whether or not the operation has all it needs to begin + BOOL checkinfoAvailable = [self.checkinPreferences hasCheckinInfo]; + _FIRInstanceIDDevAssert(checkinfoAvailable, @"Cannot fetch token invalid checkin state"); + if (!checkinfoAvailable) { + FIRInstanceIDErrorCode errorCode = kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn; + [self finishWithResult:FIRInstanceIDTokenOperationError + token:nil + error:[NSError errorWithFIRInstanceIDErrorCode:errorCode]]; + return; + } + + [self setExecuting:YES]; + + [self performTokenOperation]; +} + +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + _result = result; + // TODO(chliangGoogle): Call these in the main thread? + for (FIRInstanceIDTokenOperationCompletion completionHandler in self.completionHandlers) { + completionHandler(result, token, error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; +} + +- (void)performTokenOperation { +} + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString { + NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + // Add HTTP headers + [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"]; + [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"]; + request.HTTPMethod = @"POST"; + return request; +} + ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope { + NSMutableArray *queryItems = [NSMutableArray arrayWithCapacity:8]; + + // E.g. X-osv=10.2.1 + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]]; + // E.g. device= + if (deviceID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"device" value:deviceID]]; + } + // E.g. X-scope=fcm + if (scope) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamScope + value:scope]]; + } + // E.g. plat=2 + NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"plat" value:platform]]; + // E.g. app=com.myapp.foo + NSString *appIdentifier = FIRInstanceIDAppIdentifier(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app" value:appIdentifier]]; + // E.g. app_ver=1.5 + NSString *appVersion = FIRInstanceIDCurrentAppVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app_ver" value:appVersion]]; + // E.g. X-cliv=fiid-1.2.3 + NSString *fcmLibraryVersion = + [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()]; + if (fcmLibraryVersion.length) { + FIRInstanceIDURLQueryItem *gcmLibVersion = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion + value:fcmLibraryVersion]; + [queryItems addObject:gcmLibVersion]; + } + + return queryItems; +} + +- (NSArray *)queryItemsWithKeyPair:(FIRInstanceIDKeyPair *)keyPair { + NSMutableArray *items = [NSMutableArray arrayWithCapacity:3]; + // appid= + NSString *instanceID = FIRInstanceIDAppIdentity(keyPair); + [items addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID + value:instanceID]]; + return items; +} + +#pragma mark - HTTP Header + ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + NSString *deviceID = checkin.deviceID; + NSString *secret = checkin.secretToken; + return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret]; +} +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h new file mode 100644 index 0000000..861c87b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAPNSInfo; +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDTokenInfo; + +/** + * This class is responsible for retrieving and saving `FIRInstanceIDTokenInfo` objects from the + * keychain. The keychain keys that are used are: + * Account:
(e.g. com.mycompany.myapp) + * Service: : (e.g. 1234567890:*) + */ +@interface FIRInstanceIDTokenStore : NSObject + +NS_ASSUME_NONNULL_BEGIN + +/** + * Create a default InstanceID token store. Uses a valid Keychain object as it's + * persistent backing store. + * + * @return A valid token store object. + */ ++ (instancetype)defaultStore; + +- (instancetype)init __attribute__((unavailable("Use -initWithKeychain: instead."))); + +/** + * Initialize a token store object with a Keychain object. Used for testing. + * + * @param keychain The Keychain object to use as the backing store for tokens. + * + * @return A valid token store object with the given Keychain as backing store. + */ +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain; + +#pragma mark - Get + +/** + * Get the cached token from the Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Save + +/** + * Save the instanceID token info to the persistent store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when token saving is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(nullable void (^)(NSError *))handler; + +#pragma mark - Delete + +/** + * Remove the cached token from Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + */ +- (void)removeTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Remove all the cached tokens from the Keychain. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)removeAllTokensWithHandler:(nullable void (^)(NSError *))handler; + +NS_ASSUME_NONNULL_END + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m new file mode 100644 index 0000000..baadc89 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m @@ -0,0 +1,137 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kFIRInstanceIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstanceIDTokenStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; + +@end + +@implementation FIRInstanceIDTokenStore + ++ (instancetype)defaultStore { + FIRInstanceIDAuthKeychain *tokenKeychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDTokenKeychainId]; + return [[FIRInstanceIDTokenStore alloc] initWithKeychain:tokenKeychain]; +} + +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _keychain = keychain; + } + return self; +} + +#pragma mark - Get + ++ (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + NSData *item = [self.keychain dataForService:service account:account]; + if (!item) { + return nil; + } + // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo. + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + return tokenInfo; +} + +- (NSArray *)cachedTokenInfos { + NSString *account = FIRInstanceIDAppIdentifier(); + NSArray *items = + [self.keychain itemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier account:account]; + NSMutableArray *tokenInfos = + [NSMutableArray arrayWithCapacity:items.count]; + for (NSData *item in items) { + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + if (tokenInfo) { + [tokenInfos addObject:tokenInfo]; + } + } + return tokenInfos; +} + ++ (nullable FIRInstanceIDTokenInfo *)tokenInfoFromKeychainItem:(NSData *)item { + // Check if it is saved as an archived FIRInstanceIDTokenInfo, otherwise return nil. + FIRInstanceIDTokenInfo *tokenInfo = nil; + // NOTE: Passing in nil to unarchiveObjectWithData will result in an iOS error logged + // in the console on iOS 10 and below. Avoid by checking item.data's existence. + if (item) { + @try { + tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item]; + } @catch (NSException *exception) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo, + @"Unable to parse token info from Keychain item; item was in an " + @"invalid format"); + tokenInfo = nil; + } @finally { + } + } + return tokenInfo; +} + +#pragma mark - Save +// Token Infos will be saved under these Keychain keys: +// Account:
(e.g. com.mycompany.myapp) +// Service: : (e.g. 1234567890:*) +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *))handler { // Keep the cachetime up-to-date. + tokenInfo.cacheTime = [NSDate date]; + // Always write to the Keychain, so that the cacheTime is up-to-date. + NSData *tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo]; + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope]; + [self.keychain setData:tokenInfoData + forService:service + accessibility:NULL + account:account + handler:handler]; +} + +#pragma mark - Delete + +- (void)removeTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity + scope:(nonnull NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + [self.keychain removeItemsMatchingService:service account:account handler:nil]; +} + +- (void)removeAllTokensWithHandler:(void (^)(NSError *error))handler { + NSString *account = FIRInstanceIDAppIdentifier(); + [self.keychain removeItemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier + account:account + handler:handler]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h new file mode 100644 index 0000000..3a3a1d7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// Stand-in for NSURLQueryItem, which is only available on iOS 8.0 and up. +@interface FIRInstanceIDURLQueryItem : NSObject + +@property(nonatomic, readonly) NSString *name; +@property(nonatomic, readonly) NSString *value; + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value; +- (instancetype)initWithName:(NSString *)name value:(NSString *)value; + +@end + +/** + * Given an array of query items, construct a URL query. On iOS 8.0 and above, this will use + * NSURLQueryItems internally to perform the string creation, and will be done manually in iOS + * 7 and below. + */ +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems); + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m new file mode 100644 index 0000000..59b4865 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDURLQueryItem.h" + +@implementation FIRInstanceIDURLQueryItem + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value { + return [[[self class] alloc] initWithName:name value:value]; +} + +- (instancetype)initWithName:(NSString *)name value:(NSString *)value { + self = [super init]; + if (self) { + _name = [name copy]; + _value = [value copy]; + } + return self; +} +@end + +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems) { + if ([NSURLQueryItem class]) { + // We are iOS 8.0 and above. Convert to NSURLQueryItems and get query that way + // to take advantage of any automatic encoding + NSMutableArray *urlItems = + [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [urlItems addObject:[NSURLQueryItem queryItemWithName:queryItem.name value:queryItem.value]]; + } + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = urlItems; + return components.query; + } else { + // We are on iOS 7.0. Manually create the query string + NSMutableArray *pairs = [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [pairs addObject:[NSString stringWithFormat:@"%@=%@", queryItem.name, queryItem.value]]; + } + return [pairs componentsJoinedByString:@"&"]; + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h new file mode 100644 index 0000000..da6ebad --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFCMSDKClassString; + +/// locale key stored in GULUserDefaults +FOUNDATION_EXPORT NSString *const kFIRInstanceIDUserDefaultsKeyLocale; + +#pragma mark - Test Blocks + +/** + * Response block for mock registration requests made during tests. + * + * @param data The data as returned by the mock request. + * @param response The response as returned by the mock request. + * @param error The error if any as returned by the mock request. + */ +typedef void (^FIRInstanceIDURLRequestTestResponseBlock)(NSData *data, + NSURLResponse *response, + NSError *error); + +/** + * Test block to mock registration requests response. + * + * @param request The request to mock response for. + * @param response The response block for the mocked request. + */ +typedef void (^FIRInstanceIDURLRequestTestBlock)(NSURLRequest *request, + FIRInstanceIDURLRequestTestResponseBlock response); + +#pragma mark - URL Helpers + +FOUNDATION_EXPORT NSString *FIRInstanceIDRegisterServer(void); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentifier(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDFirebaseAppID(void); + +#pragma mark - Device Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDDeviceModel(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDOperatingSystemVersion(void); +FOUNDATION_EXPORT BOOL FIRInstanceIDHasLocaleChanged(void); + +#pragma mark - Helpers + +FOUNDATION_EXPORT BOOL FIRInstanceIDIsValidGCMScope(NSString *scope); +FOUNDATION_EXPORT NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken); +FOUNDATION_EXPORT NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, + BOOL isSandbox); + +#pragma mark - GCM Helpers +/// Returns the current GCM version if GCM library is found else returns nil. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentGCMVersion(void); + +/// Returns the current locale. If GCM is present it queries GCM for a +/// Context Manager specific locale. Otherwise, it returns the system's first +/// preferred language (which may be set independently from locale). If the +/// system returns no preferred languages, this method returns the most common +/// language for the user's given locale. Guaranteed to return a nonnull value. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLocale(void); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m new file mode 100644 index 0000000..6b7ca96 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m @@ -0,0 +1,194 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDUtilities.h" + +#import +#import + +#import +#import +#import "FIRInstanceID.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kFIRInstanceIDAPNSSandboxPrefix = @"s_"; +static NSString *const kFIRInstanceIDAPNSProdPrefix = @"p_"; + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +NSString *const kFIRInstanceIDFCMSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRInstanceIDFCMSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRInstanceIDFCMSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; + +NSString *const kFIRInstanceIDUserDefaultsKeyLocale = + @"com.firebase.instanceid.user_defaults.locale"; // locale key stored in GULUserDefaults + +/// Static values which will be populated once retrieved using +/// |FIRInstanceIDRetrieveEnvironmentInfoFromFirebaseCore|. +static NSString *operatingSystemVersion; +static NSString *hardwareDeviceModel; + +#pragma mark - URL Helpers + +NSString *FIRInstanceIDRegisterServer() { + return @"https://fcmtoken.googleapis.com/register"; +} + +#pragma mark - Time + +int64_t FIRInstanceIDCurrentTimestampInSeconds() { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRInstanceIDCurrentTimestampInMilliseconds() { + return (int64_t)(FIRInstanceIDCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRInstanceIDCurrentAppVersion() { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + return @""; + } + return version; +} + +NSString *FIRInstanceIDAppIdentifier() { + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleIdentifier.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier, + @"The mainBundle's bundleIdentifier returned '%@'. Bundle identifier " + @"expected to be non-empty.", + bundleIdentifier); + return @""; + } + return bundleIdentifier; +} + +NSString *FIRInstanceIDFirebaseAppID() { + return [FIROptions defaultOptions].googleAppID; +} + +#pragma mark - Device Info +// Get the device model from Firebase Core's App Environment Util +NSString *FIRInstanceIDDeviceModel() { + static dispatch_once_t once; + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + hardwareDeviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return hardwareDeviceModel; +} + +// Get the system version from Firebase Core's App Environment Util +NSString *FIRInstanceIDOperatingSystemVersion() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX + return [NSProcessInfo processInfo].operatingSystemVersionString; +#endif +} + +BOOL FIRInstanceIDHasLocaleChanged() { + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + if (lastLocale) { + if ([currentLocale isEqualToString:lastLocale]) { + return NO; + } + } + return YES; +} + +#pragma mark - Helpers + +BOOL FIRInstanceIDIsValidGCMScope(NSString *scope) { + return [scope compare:kFIRInstanceIDScopeFirebaseMessaging + options:NSCaseInsensitiveSearch] == NSOrderedSame; +} + +NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken) { + NSMutableString *APNSToken = [NSMutableString string]; + unsigned char *bytes = (unsigned char *)[deviceToken bytes]; + for (int i = 0; i < (int)deviceToken.length; i++) { + [APNSToken appendFormat:@"%02x", bytes[i]]; + } + return APNSToken; +} + +NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, BOOL isSandbox) { + if (deviceToken == nil) { + // A nil deviceToken leads to an invalid tuple string, so return nil. + return nil; + } + NSString *prefix = isSandbox ? kFIRInstanceIDAPNSSandboxPrefix : kFIRInstanceIDAPNSProdPrefix; + NSString *APNSString = FIRInstanceIDStringForAPNSDeviceToken(deviceToken); + NSString *APNSTupleString = [NSString stringWithFormat:@"%@%@", prefix, APNSString]; + + return APNSTupleString; +} + +#pragma mark - GCM Helpers + +NSString *FIRInstanceIDCurrentGCMVersion() { + Class versionClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL versionSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKVersionSelectorString); + if ([versionClass respondsToSelector:versionSelector]) { + IMP getVersionIMP = [versionClass methodForSelector:versionSelector]; + NSString *(*getVersion)(id, SEL) = (void *)getVersionIMP; + return getVersion(versionClass, versionSelector); + } + return nil; +} + +NSString *FIRInstanceIDCurrentLocale() { + Class localeClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL localeSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKLocaleSelectorString); + + if ([localeClass respondsToSelector:localeSelector]) { + IMP getLocaleIMP = [localeClass methodForSelector:localeSelector]; + NSString *(*getLocale)(id, SEL) = (void *)getLocaleIMP; + NSString *fcmLocale = getLocale(localeClass, localeSelector); + if (fcmLocale != nil) { + return fcmLocale; + } + } + + NSString *systemLanguage = [[NSLocale preferredLanguages] firstObject]; + if (systemLanguage != nil) { + return systemLanguage; + } + + if (@available(iOS 10.0, *)) { + return [NSLocale currentLocale].languageCode; + } else { + return nil; + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h new file mode 100644 index 0000000..ec5a76c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Parsing utility for InstanceID Library versions. InstanceID lib follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLibraryVersion(void); +/// Returns the current Major version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRInstanceIDCurrentLibraryVersionIsBeta(void); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m new file mode 100644 index 0000000..d6b0945 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDVersionUtilities.h" + +#import "FIRInstanceIDDefines.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; + +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRInstanceIDParseCurrentLibraryVersion() { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = + [NSMutableString stringWithUTF8String:STR(FIRInstanceID_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + _FIRInstanceIDDevAssert(allVersions.count == 3, @"Invalid versioning of FIRInstanceID library"); + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + _FIRInstanceIDDevAssert(patchAndBetaVersion.count <= 2, + @"Invalid versioning of FIRInstanceID library"); + + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRInstanceIDCurrentLibraryVersion() { + FIRInstanceIDParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMajor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMinor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionPatch() { + FIRInstanceIDParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRInstanceIDCurrentLibraryVersionIsBeta() { + FIRInstanceIDParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h new file mode 100644 index 0000000..b533dc4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDomain; + +typedef NS_ENUM(NSUInteger, FIRInstanceIDErrorCode) { + // Unknown error. + kFIRInstanceIDErrorCodeUnknown = 0, + + // Http related errors. + kFIRInstanceIDErrorCodeAuthentication = 1, + kFIRInstanceIDErrorCodeNoAccess = 2, + kFIRInstanceIDErrorCodeTimeout = 3, + kFIRInstanceIDErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRInstanceIDErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRInstanceIDErrorCodeInvalidRequest = 7, + + // InstanceID generic errors + kFIRInstanceIDErrorCodeMissingDeviceID = 501, + + // InstanceID Token specific errors + kFIRInstanceIDErrorCodeMissingAPNSToken = 1001, + kFIRInstanceIDErrorCodeMissingAPNSServerType = 1002, + kFIRInstanceIDErrorCodeInvalidAuthorizedEntity = 1003, + kFIRInstanceIDErrorCodeInvalidScope = 1004, + kFIRInstanceIDErrorCodeInvalidStart = 1005, + kFIRInstanceIDErrorCodeInvalidKeyPair = 1006, + + // InstanceID Identity specific errors + // Generic InstanceID keypair error + kFIRInstanceIDErrorCodeMissingKeyPair = 2001, + kFIRInstanceIDErrorCodeInvalidKeyPairTags = 2002, + kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime = 2005, + kFIRInstanceIDErrorCodeInvalidIdentity = 2006, + +}; + +@interface NSError (FIRInstanceID) + +@property(nonatomic, readonly) FIRInstanceIDErrorCode instanceIDErrorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo; + ++ (NSError *)FIRInstanceIDErrorMissingCheckin; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m new file mode 100644 index 0000000..560a5df --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRInstanceID.h" + +NSString *const kFIRInstanceIDDomain = @"com.firebase.iid"; + +@implementation NSError (FIRInstanceID) + +- (FIRInstanceIDErrorCode)instanceIDErrorCode { + return (FIRInstanceIDErrorCode)self.code; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode { + return [NSError errorWithFIRInstanceIDErrorCode:errorCode userInfo:nil]; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRInstanceIDDomain code:errorCode userInfo:userInfo]; +} + ++ (NSError *)FIRInstanceIDErrorMissingCheckin { + NSDictionary *userInfo = @{@"msg" : @"Missing device credentials. Retry later."}; + + return [NSError errorWithDomain:kFIRInstanceIDDomain + code:kFIRInstanceIDErrorCodeMissingDeviceID + userInfo:userInfo]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h new file mode 100644 index 0000000..6a9e2d3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Private API used by other Firebase SDKs. + */ +@interface FIRInstanceID () + +/** + * Private initializer. + */ +- (nonnull instancetype)initPrivately; + +/** + * Returns a Firebase Messaging scoped token for the firebase app. + * + * @return Returns the stored token if the device has registered with Firebase Messaging, otherwise + * returns nil. + */ +- (nullable NSString *)token; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h new file mode 100644 index 0000000..c187d55 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h @@ -0,0 +1,312 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDResult; +/** + * @memberof FIRInstanceID + * + * The scope to be used when fetching/deleting a token for Firebase Messaging. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDScopeFirebaseMessaging + NS_SWIFT_NAME(InstanceIDScopeFirebaseMessaging); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT const NSNotificationName kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefresh); +#else +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefreshNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID token returns. If + * the call fails we return the appropriate `error code` as described below. + * + * @param token The valid token as returned by InstanceID backend. + * + * @param error The error describing why generating a new token + * failed. See the error codes below for a more detailed + * description. + */ +typedef void (^FIRInstanceIDTokenHandler)(NSString *__nullable token, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID `deleteToken` returns. If + * the call fails we return the appropriate `error code` as described below + * + * @param error The error describing why deleting the token failed. + * See the error codes below for a more detailed description. + */ +typedef void (^FIRInstanceIDDeleteTokenHandler)(NSError *error) + NS_SWIFT_NAME(InstanceIDDeleteTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity is created. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param identity A valid identity for the app instance, nil if there was an error + * while creating an identity. + * @param error The error if fetching the identity fails else nil. + */ +typedef void (^FIRInstanceIDHandler)(NSString *__nullable identity, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and all the tokens associated + * with it are deleted. Returns a valid error object in case of failure else nil. + * + * @param error The error if deleting the identity and all the tokens associated with + * it fails else nil. + */ +typedef void (^FIRInstanceIDDeleteHandler)(NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDDeleteHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and token are fetched. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param result The result containing an identity for the app instance and a valid token, + * nil if there was an error while creating the result. + * @param error The error if fetching the identity or token fails else nil. + */ +typedef void (^FIRInstanceIDResultHandler)(FIRInstanceIDResult *__nullable result, + NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDResultHandler); + +/** + * Public errors produced by InstanceID. + */ +typedef NS_ENUM(NSUInteger, FIRInstanceIDError) { + // Http related errors. + + /// Unknown error. + FIRInstanceIDErrorUnknown = 0, + + /// Auth Error -- GCM couldn't validate request from this client. + FIRInstanceIDErrorAuthentication = 1, + + /// NoAccess -- InstanceID service cannot be accessed. + FIRInstanceIDErrorNoAccess = 2, + + /// Timeout -- Request to InstanceID backend timed out. + FIRInstanceIDErrorTimeout = 3, + + /// Network -- No network available to reach the servers. + FIRInstanceIDErrorNetwork = 4, + + /// OperationInProgress -- Another similar operation in progress, + /// bailing this one. + FIRInstanceIDErrorOperationInProgress = 5, + + /// InvalidRequest -- Some parameters of the request were invalid. + FIRInstanceIDErrorInvalidRequest = 7, +} NS_SWIFT_NAME(InstanceIDError); + +/** + * A class contains the results of InstanceID and token query. + */ +NS_SWIFT_NAME(InstanceIDResult) +@interface FIRInstanceIDResult : NSObject + +/** + * An instanceID uniquely identifies the app instance. + */ +@property(nonatomic, readonly, copy) NSString *instanceID; + +/* + * Returns a Firebase Messaging scoped token for the firebase app. + */ +@property(nonatomic, readonly, copy) NSString *token; + +@end + +/** + * Instance ID provides a unique identifier for each app instance and a mechanism + * to authenticate and authorize actions (for example, sending an FCM message). + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * Instance ID is long lived but, may be reset if the device is not used for + * a long time or the Instance ID service detects a problem. + * If Instance ID is reset, the app will be notified via + * `kFIRInstanceIDTokenRefreshNotification`. + * + * If the Instance ID has become invalid, the app can request a new one and + * send it to the app server. + * To prove ownership of Instance ID and to allow servers to access data or + * services associated with the app, call + * `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + */ +NS_SWIFT_NAME(InstanceID) +@interface FIRInstanceID : NSObject + +/** + * FIRInstanceID. + * + * @return A shared instance of FIRInstanceID. + */ ++ (instancetype)instanceID NS_SWIFT_NAME(instanceID()); + +/** + * Unavailable. Use +instanceID instead. + */ +- (instancetype)init __attribute__((unavailable("Use +instanceID instead."))); + +#pragma mark - Tokens + +/** + * Returns a result of app instance identifier InstanceID and a Firebase Messaging scoped token. + * param handler The callback handler invoked when an app instanceID and a default token + * are generated and returned. If instanceID and token fetching fail for some + * reason the callback is invoked with nil `result` and the appropriate error. + */ +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler; + +/** + * Returns a token that authorizes an Entity (example: cloud service) to perform + * an action on behalf of the application identified by Instance ID. + * + * This is similar to an OAuth2 token except, it applies to the + * application instance instead of a user. + * + * This is an asynchronous call. If the token fetching fails for some reason + * we invoke the completion callback with nil `token` and the appropriate + * error. + * + * This generates an Instance ID if it does not exist yet, which starts periodically sending + * information to the Firebase backend (see `[FIRInstanceID getIDWithHandler:]`). + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at any point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an + * error with code `OperationInProgress`. + * + * @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler: + * + * @param authorizedEntity Entity authorized by the token. + * @param scope Action authorized for authorizedEntity. + * @param options The extra options to be sent with your token request. The + * value for the `apns_token` should be the NSData object + * passed to the UIApplicationDelegate's + * `didRegisterForRemoteNotificationsWithDeviceToken` method. + * The value for `apns_sandbox` should be a boolean (or an + * NSNumber representing a BOOL in Objective C) set to true if + * your app is a debug build, which means that the APNs + * device token is for the sandbox environment. It should be + * set to false otherwise. If the `apns_sandbox` key is not + * provided, an automatically-detected value shall be used. + * @param handler The callback handler which is invoked when the token is + * successfully fetched. In case of success a valid `token` and + * `nil` error are returned. In case of any error the `token` + * is nil and a valid `error` is returned. The valid error + * codes have been documented above. + */ +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Revokes access to a scope (action) for an entity previously + * authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + * + * This is an asynchronous call. Call this on the main thread since InstanceID lib + * is not thread safe. In case token deletion fails for some reason we invoke the + * `handler` callback passed in with the appropriate error code. + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at a point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an error + * with code `OperationInProgress`. + * + * @param authorizedEntity Entity that must no longer have access. + * @param scope Action that entity is no longer authorized to perform. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of error an appropriate error object is returned + * else error is nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +#pragma mark - Identity + +/** + * Asynchronously fetch a stable identifier that uniquely identifies the app + * instance. If the identifier has been revoked or has expired, this method will + * return a new identifier. + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * @param handler The handler to invoke once the identifier has been fetched. + * In case of error an appropriate error object is returned else + * a valid identifier is returned and a valid identifier for the + * application instance. + */ +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler NS_SWIFT_NAME(getID(handler:)); + +/** + * Resets Instance ID and revokes all tokens. + * + * This method also triggers a request to fetch a new Instance ID and Firebase Messaging scope + * token. Please listen to kFIRInstanceIDTokenRefreshNotification when the new ID and token are + * ready. + * + * This stops the periodic sending of data to the Firebase backend that began when the Instance ID + * was generated. No more data is sent until another library calls Instance ID internally again + * (like FCM, RemoteConfig or Analytics) or user explicitly calls Instance ID APIs to get an + * Instance ID and token again. + */ +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler NS_SWIFT_NAME(deleteID(handler:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h new file mode 100644 index 0000000..78c9ef1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h @@ -0,0 +1,17 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseInstanceID/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMMessageCode.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMMessageCode.h new file mode 100644 index 0000000..4c47838 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMMessageCode.h @@ -0,0 +1,199 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) { + // FIRMessaging+FIRApp.m + kFIRMessagingMessageCodeFIRApp000 = 1000, // I-FCM001000 + kFIRMessagingMessageCodeFIRApp001 = 1001, // I-FCM001001 + // FIRMessaging.m + kFIRMessagingMessageCodeMessagingPrintLibraryVersion = 2000, // I-FCM002000 + kFIRMessagingMessageCodeMessaging001 = 2001, // I-FCM002001 + kFIRMessagingMessageCodeMessaging002 = 2002, // I-FCM002002 - no longer used + kFIRMessagingMessageCodeMessaging003 = 2003, // I-FCM002003 + kFIRMessagingMessageCodeMessaging004 = 2004, // I-FCM002004 + kFIRMessagingMessageCodeMessaging005 = 2005, // I-FCM002005 + kFIRMessagingMessageCodeMessaging006 = 2006, // I-FCM002006 - no longer used + kFIRMessagingMessageCodeMessaging007 = 2007, // I-FCM002007 - no longer used + kFIRMessagingMessageCodeMessaging008 = 2008, // I-FCM002008 - no longer used + kFIRMessagingMessageCodeMessaging009 = 2009, // I-FCM002009 + kFIRMessagingMessageCodeMessaging010 = 2010, // I-FCM002010 + kFIRMessagingMessageCodeMessaging011 = 2011, // I-FCM002011 + kFIRMessagingMessageCodeMessaging012 = 2012, // I-FCM002012 + kFIRMessagingMessageCodeMessaging013 = 2013, // I-FCM002013 + kFIRMessagingMessageCodeMessaging014 = 2014, // I-FCM002014 + kFIRMessagingMessageCodeMessaging015 = 2015, // I-FCM002015 + kFIRMessagingMessageCodeMessaging016 = 2016, // I-FCM002016 - no longer used + kFIRMessagingMessageCodeMessaging017 = 2017, // I-FCM002017 + kFIRMessagingMessageCodeMessaging018 = 2018, // I-FCM002018 + kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented = 2019, // I-FCM002019 + kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenFetch = 2020, // I-FCM002020 + kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenDelete = 2021, // I-FCM002021 + kFIRMessagingMessageCodeAPNSTokenNotAvailableDuringTokenFetch = 2022, // I-FCM002022 + kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented = 2023, // I-FCM002023 + kFIRMessagingMessageCodeTopicFormatIsDeprecated = 2024, + kFIRMessagingMessageCodeDirectChannelConnectionFailed = 2025, + // FIRMessagingClient.m + kFIRMessagingMessageCodeClient000 = 4000, // I-FCM004000 + kFIRMessagingMessageCodeClient001 = 4001, // I-FCM004001 + kFIRMessagingMessageCodeClient002 = 4002, // I-FCM004002 + kFIRMessagingMessageCodeClient003 = 4003, // I-FCM004003 + kFIRMessagingMessageCodeClient004 = 4004, // I-FCM004004 + kFIRMessagingMessageCodeClient005 = 4005, // I-FCM004005 + kFIRMessagingMessageCodeClient006 = 4006, // I-FCM004006 + kFIRMessagingMessageCodeClient007 = 4007, // I-FCM004007 + kFIRMessagingMessageCodeClient008 = 4008, // I-FCM004008 + kFIRMessagingMessageCodeClient009 = 4009, // I-FCM004009 + kFIRMessagingMessageCodeClient010 = 4010, // I-FCM004010 + kFIRMessagingMessageCodeClient011 = 4011, // I-FCM004011 + // FIRMessagingConnection.m + kFIRMessagingMessageCodeConnection000 = 5000, // I-FCM005000 + kFIRMessagingMessageCodeConnection001 = 5001, // I-FCM005001 + kFIRMessagingMessageCodeConnection002 = 5002, // I-FCM005002 + kFIRMessagingMessageCodeConnection003 = 5003, // I-FCM005003 + kFIRMessagingMessageCodeConnection004 = 5004, // I-FCM005004 + kFIRMessagingMessageCodeConnection005 = 5005, // I-FCM005005 + kFIRMessagingMessageCodeConnection006 = 5006, // I-FCM005006 + kFIRMessagingMessageCodeConnection007 = 5007, // I-FCM005007 + kFIRMessagingMessageCodeConnection008 = 5008, // I-FCM005008 + kFIRMessagingMessageCodeConnection009 = 5009, // I-FCM005009 + kFIRMessagingMessageCodeConnection010 = 5010, // I-FCM005010 + kFIRMessagingMessageCodeConnection011 = 5011, // I-FCM005011 + kFIRMessagingMessageCodeConnection012 = 5012, // I-FCM005012 + kFIRMessagingMessageCodeConnection013 = 5013, // I-FCM005013 + kFIRMessagingMessageCodeConnection014 = 5014, // I-FCM005014 + kFIRMessagingMessageCodeConnection015 = 5015, // I-FCM005015 + kFIRMessagingMessageCodeConnection016 = 5016, // I-FCM005016 + kFIRMessagingMessageCodeConnection017 = 5017, // I-FCM005017 + kFIRMessagingMessageCodeConnection018 = 5018, // I-FCM005018 + kFIRMessagingMessageCodeConnection019 = 5019, // I-FCM005019 + kFIRMessagingMessageCodeConnection020 = 5020, // I-FCM005020 + kFIRMessagingMessageCodeConnection021 = 5021, // I-FCM005021 + kFIRMessagingMessageCodeConnection022 = 5022, // I-FCM005022 + kFIRMessagingMessageCodeConnection023 = 5023, // I-FCM005023 + // FIRMessagingContextManagerService.m + kFIRMessagingMessageCodeContextManagerService000 = 6000, // I-FCM006000 + kFIRMessagingMessageCodeContextManagerService001 = 6001, // I-FCM006001 + kFIRMessagingMessageCodeContextManagerService002 = 6002, // I-FCM006002 + kFIRMessagingMessageCodeContextManagerService003 = 6003, // I-FCM006003 + kFIRMessagingMessageCodeContextManagerService004 = 6004, // I-FCM006004 + kFIRMessagingMessageCodeContextManagerService005 = 6005, // I-FCM006005 + // FIRMessagingDataMessageManager.m + kFIRMessagingMessageCodeDataMessageManager000 = 7000, // I-FCM007000 + kFIRMessagingMessageCodeDataMessageManager001 = 7001, // I-FCM007001 + kFIRMessagingMessageCodeDataMessageManager002 = 7002, // I-FCM007002 + kFIRMessagingMessageCodeDataMessageManager003 = 7003, // I-FCM007003 + kFIRMessagingMessageCodeDataMessageManager004 = 7004, // I-FCM007004 + kFIRMessagingMessageCodeDataMessageManager005 = 7005, // I-FCM007005 + kFIRMessagingMessageCodeDataMessageManager006 = 7006, // I-FCM007006 + kFIRMessagingMessageCodeDataMessageManager007 = 7007, // I-FCM007007 + kFIRMessagingMessageCodeDataMessageManager008 = 7008, // I-FCM007008 + kFIRMessagingMessageCodeDataMessageManager009 = 7009, // I-FCM007009 + kFIRMessagingMessageCodeDataMessageManager010 = 7010, // I-FCM007010 + kFIRMessagingMessageCodeDataMessageManager011 = 7011, // I-FCM007011 + kFIRMessagingMessageCodeDataMessageManager012 = 7012, // I-FCM007012 + // FIRMessagingPendingTopicsList.m + kFIRMessagingMessageCodePendingTopicsList000 = 8000, // I-FCM008000 + // FIRMessagingPubSub.m + kFIRMessagingMessageCodePubSub000 = 9000, // I-FCM009000 + kFIRMessagingMessageCodePubSub001 = 9001, // I-FCM009001 + kFIRMessagingMessageCodePubSub002 = 9002, // I-FCM009002 + kFIRMessagingMessageCodePubSub003 = 9003, // I-FCM009003 + // FIRMessagingReceiver.m + kFIRMessagingMessageCodeReceiver000 = 10000, // I-FCM010000 + kFIRMessagingMessageCodeReceiver001 = 10001, // I-FCM010001 + kFIRMessagingMessageCodeReceiver002 = 10002, // I-FCM010002 + kFIRMessagingMessageCodeReceiver003 = 10003, // I-FCM010003 + kFIRMessagingMessageCodeReceiver004 = 10004, // I-FCM010004 - no longer used + kFIRMessagingMessageCodeReceiver005 = 10005, // I-FCM010005 + // FIRMessagingRegistrar.m + kFIRMessagingMessageCodeRegistrar000 = 11000, // I-FCM011000 + // FIRMessagingRemoteNotificationsProxy.m + kFIRMessagingMessageCodeRemoteNotificationsProxy000 = 12000, // I-FCM012000 + kFIRMessagingMessageCodeRemoteNotificationsProxy001 = 12001, // I-FCM012001 + kFIRMessagingMessageCodeRemoteNotificationsProxyAPNSFailed = 12002, // I-FCM012002 + kFIRMessagingMessageCodeRemoteNotificationsProxyMethodNotAdded = 12003, // I-FCM012003 + // FIRMessagingRmq2PersistentStore.m + kFIRMessagingMessageCodeRmq2PersistentStore000 = 13000, // I-FCM013000 + kFIRMessagingMessageCodeRmq2PersistentStore001 = 13001, // I-FCM013001 + kFIRMessagingMessageCodeRmq2PersistentStore002 = 13002, // I-FCM013002 + kFIRMessagingMessageCodeRmq2PersistentStore003 = 13003, // I-FCM013003 + kFIRMessagingMessageCodeRmq2PersistentStore004 = 13004, // I-FCM013004 + kFIRMessagingMessageCodeRmq2PersistentStore005 = 13005, // I-FCM013005 + kFIRMessagingMessageCodeRmq2PersistentStore006 = 13006, // I-FCM013006 + kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingDatabase = 13007, // I-FCM013007 + kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase = 13008, // I-FCM013008 + kFIRMessagingMessageCodeRmq2PersistentStoreInvalidRmqDirectory = 13009, // I-FCM013009 + kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingTable = 13010, // I-FCM013010 + // FIRMessagingRmqManager.m + kFIRMessagingMessageCodeRmqManager000 = 14000, // I-FCM014000 + // FIRMessagingSecureSocket.m + kFIRMessagingMessageCodeSecureSocket000 = 15000, // I-FCM015000 + kFIRMessagingMessageCodeSecureSocket001 = 15001, // I-FCM015001 + kFIRMessagingMessageCodeSecureSocket002 = 15002, // I-FCM015002 + kFIRMessagingMessageCodeSecureSocket003 = 15003, // I-FCM015003 + kFIRMessagingMessageCodeSecureSocket004 = 15004, // I-FCM015004 + kFIRMessagingMessageCodeSecureSocket005 = 15005, // I-FCM015005 + kFIRMessagingMessageCodeSecureSocket006 = 15006, // I-FCM015006 + kFIRMessagingMessageCodeSecureSocket007 = 15007, // I-FCM015007 + kFIRMessagingMessageCodeSecureSocket008 = 15008, // I-FCM015008 + kFIRMessagingMessageCodeSecureSocket009 = 15009, // I-FCM015009 + kFIRMessagingMessageCodeSecureSocket010 = 15010, // I-FCM015010 + kFIRMessagingMessageCodeSecureSocket011 = 15011, // I-FCM015011 + kFIRMessagingMessageCodeSecureSocket012 = 15012, // I-FCM015012 + kFIRMessagingMessageCodeSecureSocket013 = 15013, // I-FCM015013 + kFIRMessagingMessageCodeSecureSocket014 = 15014, // I-FCM015014 + kFIRMessagingMessageCodeSecureSocket015 = 15015, // I-FCM015015 + kFIRMessagingMessageCodeSecureSocket016 = 15016, // I-FCM015016 + // FIRMessagingSyncMessageManager.m + kFIRMessagingMessageCodeSyncMessageManager000 = 16000, // I-FCM016000 + kFIRMessagingMessageCodeSyncMessageManager001 = 16001, // I-FCM016001 + kFIRMessagingMessageCodeSyncMessageManager002 = 16002, // I-FCM016002 + kFIRMessagingMessageCodeSyncMessageManager003 = 16003, // I-FCM016003 + kFIRMessagingMessageCodeSyncMessageManager004 = 16004, // I-FCM016004 + kFIRMessagingMessageCodeSyncMessageManager005 = 16005, // I-FCM016005 + kFIRMessagingMessageCodeSyncMessageManager006 = 16006, // I-FCM016006 + kFIRMessagingMessageCodeSyncMessageManager007 = 16007, // I-FCM016007 + kFIRMessagingMessageCodeSyncMessageManager008 = 16008, // I-FCM016008 + // FIRMessagingTopicOperation.m + kFIRMessagingMessageCodeTopicOption000 = 17000, // I-FCM017000 + kFIRMessagingMessageCodeTopicOption001 = 17001, // I-FCM017001 + kFIRMessagingMessageCodeTopicOption002 = 17002, // I-FCM017002 + kFIRMessagingMessageCodeTopicOptionTopicEncodingFailed = 17003, // I-FCM017003 + kFIRMessagingMessageCodeTopicOperationEmptyResponse = 17004, // I-FCM017004 + // FIRMessagingUtilities.m + kFIRMessagingMessageCodeUtilities000 = 18000, // I-FCM018000 + kFIRMessagingMessageCodeUtilities001 = 18001, // I-FCM018001 + kFIRMessagingMessageCodeUtilities002 = 18002, // I-FCM018002 + // FIRMessagingAnalytics.m + kFIRMessagingMessageCodeAnalytics000 = 19000, // I-FCM019000 + kFIRMessagingMessageCodeAnalytics001 = 19001, // I-FCM019001 + kFIRMessagingMessageCodeAnalytics002 = 19002, // I-FCM019002 + kFIRMessagingMessageCodeAnalytics003 = 19003, // I-FCM019003 + kFIRMessagingMessageCodeAnalytics004 = 19004, // I-FCM019004 + kFIRMessagingMessageCodeAnalytics005 = 19005, // I-FCM019005 + kFIRMessagingMessageCodeAnalyticsInvalidEvent = 19006, // I-FCM019006 + kFIRMessagingMessageCodeAnalytics007 = 19007, // I-FCM019007 + kFIRMessagingMessageCodeAnalyticsCouldNotInvokeAnalyticsLog = 19008, // I-FCM019008 + + // FIRMessagingExtensionHelper.m + kFIRMessagingServiceExtensionImageInvalidURL = 20000, + kFIRMessagingServiceExtensionImageNotDownloaded = 20001, + kFIRMessagingServiceExtensionLocalFileNotCreated = 20002, + kFIRMessagingServiceExtensionImageNotAttached = 20003, + +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging.m new file mode 100644 index 0000000..7e6653b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging.m @@ -0,0 +1,1195 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !__has_feature(objc_arc) +#error FIRMessagingLib should be compiled with ARC. +#endif + +#import "FIRMessaging.h" +#import "FIRMessaging_Private.h" + +#import + +#import "FIRMessagingAnalytics.h" +#import "FIRMessagingClient.h" +#import "FIRMessagingConstants.h" +#import "FIRMessagingContextManagerService.h" +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingExtensionHelper.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPubSub.h" +#import "FIRMessagingReceiver.h" +#import "FIRMessagingRemoteNotificationsProxy.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingSyncMessageManager.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessagingVersionUtilities.h" +#import "FIRMessaging_Private.h" + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import "NSError+FIRMessaging.h" + +static NSString *const kFIRMessagingMessageViaAPNSRootKey = @"aps"; +static NSString *const kFIRMessagingReachabilityHostname = @"www.google.com"; +static NSString *const kFIRMessagingDefaultTokenScope = @"*"; +static NSString *const kFIRMessagingFCMTokenFetchAPNSOption = @"apns_token"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName FIRMessagingSendSuccessNotification = + @"com.firebase.messaging.notif.send-success"; +const NSNotificationName FIRMessagingSendErrorNotification = + @"com.firebase.messaging.notif.send-error"; +const NSNotificationName FIRMessagingMessagesDeletedNotification = + @"com.firebase.messaging.notif.messages-deleted"; +const NSNotificationName FIRMessagingConnectionStateChangedNotification = + @"com.firebase.messaging.notif.connection-state-changed"; +const NSNotificationName FIRMessagingRegistrationTokenRefreshedNotification = + @"com.firebase.messaging.notif.fcm-token-refreshed"; +#else +NSString *const FIRMessagingSendSuccessNotification = + @"com.firebase.messaging.notif.send-success"; +NSString *const FIRMessagingSendErrorNotification = + @"com.firebase.messaging.notif.send-error"; +NSString * const FIRMessagingMessagesDeletedNotification = + @"com.firebase.messaging.notif.messages-deleted"; +NSString * const FIRMessagingConnectionStateChangedNotification = + @"com.firebase.messaging.notif.connection-state-changed"; +NSString * const FIRMessagingRegistrationTokenRefreshedNotification = + @"com.firebase.messaging.notif.fcm-token-refreshed"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled = + @"com.firebase.messaging.auto-init.enabled"; // Auto Init Enabled key stored in NSUserDefaults + +NSString *const kFIRMessagingAPNSTokenType = @"APNSTokenType"; // APNS Token type key stored in user info. + +NSString *const kFIRMessagingPlistAutoInitEnabled = + @"FirebaseMessagingAutoInitEnabled"; // Auto Init Enabled key stored in Info.plist + +@interface FIRMessagingMessageInfo () + +@property(nonatomic, readwrite, assign) FIRMessagingMessageStatus status; + +@end + +@implementation FIRMessagingMessageInfo + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithStatus:(FIRMessagingMessageStatus)status { + self = [super init]; + if (self) { + _status = status; + } + return self; +} + +@end + +#pragma mark - for iOS 10 compatibility +@implementation FIRMessagingRemoteMessage + +- (instancetype)init { + self = [super init]; + if (self) { + _appData = [[NSMutableDictionary alloc] init]; + } + + return self; +} + +@end + +@interface FIRMessaging () + +// FIRApp properties +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; +@property(nonatomic, readwrite, strong) NSString *defaultFcmToken; + +@property(nonatomic, readwrite, strong) FIRInstanceID *instanceID; + +@property(nonatomic, readwrite, assign) BOOL isClientSetup; + +@property(nonatomic, readwrite, strong) FIRMessagingClient *client; +@property(nonatomic, readwrite, strong) GULReachabilityChecker *reachability; +@property(nonatomic, readwrite, strong) FIRMessagingDataMessageManager *dataMessageManager; +@property(nonatomic, readwrite, strong) FIRMessagingPubSub *pubsub; +@property(nonatomic, readwrite, strong) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, strong) FIRMessagingReceiver *receiver; +@property(nonatomic, readwrite, strong) FIRMessagingSyncMessageManager *syncMessageManager; +@property(nonatomic, readwrite, strong) GULUserDefaults *messagingUserDefaults; + +/// Message ID's logged for analytics. This prevents us from logging the same message twice +/// which can happen if the user inadvertently calls `appDidReceiveMessage` along with us +/// calling it implicitly during swizzling. +@property(nonatomic, readwrite, strong) NSMutableSet *loggedMessageIDs; +@property(nonatomic, readwrite, strong) id _Nullable analytics; + +@end + +// Messaging doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRMessagingInstanceProvider +@end + +@interface FIRMessaging () +@end + +@implementation FIRMessaging + ++ (FIRMessaging *)messaging { + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + id instance = + FIR_COMPONENT(FIRMessagingInstanceProvider, defaultApp.container); + + // We know the instance coming from the container is a FIRMessaging instance, cast it and move on. + FIRMessaging *messaging = (FIRMessaging *)instance; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [messaging start]; + }); + return messaging; +} + ++ (FIRMessagingExtensionHelper *)extensionHelper { + static dispatch_once_t once; + static FIRMessagingExtensionHelper *extensionHelper; + dispatch_once(&once, ^{ + extensionHelper = [[FIRMessagingExtensionHelper alloc] init]; + }); + return extensionHelper; +} + +- (instancetype)initWithAnalytics:(nullable id)analytics + withInstanceID:(FIRInstanceID *)instanceID + withUserDefaults:(GULUserDefaults *)defaults { + self = [super init]; + if (self != nil) { + _loggedMessageIDs = [NSMutableSet set]; + _instanceID = instanceID; + _messagingUserDefaults = defaults; + _analytics = analytics; + } + return self; +} + +- (void)dealloc { + [self.reachability stop]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [self teardown]; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-fcm" + withVersion:FIRMessagingCurrentLibraryVersion()]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRDependency *analyticsDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAnalyticsInterop) isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // Ensure it's cached so it returns the same instance every time messaging is called. + *isCacheable = YES; + id analytics = FIR_COMPONENT(FIRAnalyticsInterop, container); + return [[FIRMessaging alloc] initWithAnalytics:analytics + withInstanceID:[FIRInstanceID instanceID] + withUserDefaults:[GULUserDefaults standardUserDefaults]]; + }; + FIRComponent *messagingProvider = + [FIRComponent componentWithProtocol:@protocol(FIRMessagingInstanceProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ analyticsDep ] + creationBlock:creationBlock]; + + return @[ messagingProvider ]; +} + ++ (void)configureWithApp:(FIRApp *)app { + if (!app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeFIRApp001, + @"Firebase Messaging only works with the default app."); + return; + } + [[FIRMessaging messaging] configureMessaging:app]; +} + +- (void)configureMessaging:(FIRApp *)app { + // Swizzle remote-notification-related methods (app delegate and UNUserNotificationCenter) + if ([FIRMessagingRemoteNotificationsProxy canSwizzleMethods]) { + NSString *docsURLString = @"https://firebase.google.com/docs/cloud-messaging/ios/client" + @"#method_swizzling_in_firebase_messaging"; + FIRMessagingLoggerNotice(kFIRMessagingMessageCodeFIRApp000, + @"FIRMessaging Remote Notifications proxy enabled, will swizzle " + @"remote notification receiver handlers. If you'd prefer to manually " + @"integrate Firebase Messaging, add \"%@\" to your Info.plist, " + @"and set it to NO. Follow the instructions at:\n%@\nto ensure " + @"proper integration.", + kFIRMessagingRemoteNotificationsProxyEnabledInfoPlistKey, + docsURLString); + [[FIRMessagingRemoteNotificationsProxy sharedProxy] swizzleMethodsIfPossible]; + } +} + +- (void)start { + // Print the library version for logging. + NSString *currentLibraryVersion = FIRMessagingCurrentLibraryVersion(); + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeMessagingPrintLibraryVersion, + @"FIRMessaging library version %@", + currentLibraryVersion); + + [self setupReceiver]; + + NSString *hostname = kFIRMessagingReachabilityHostname; + self.reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:hostname]; + [self.reachability start]; + + [self setupFileManagerSubDirectory]; + // setup FIRMessaging objects + [self setupRmqManager]; + [self setupClient]; + [self setupSyncMessageManager]; + [self setupDataMessageManager]; + [self setupTopics]; + + self.isClientSetup = YES; + [self setupNotificationListeners]; +} + +- (void)setupFileManagerSubDirectory { + if (![[self class] hasSubDirectory:kFIRMessagingSubDirectoryName]) { + [[self class] createSubDirectory:kFIRMessagingSubDirectoryName]; + } +} + +- (void)setupNotificationListeners { + // To prevent multiple notifications remove self as observer for all events. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + + [center addObserver:self + selector:@selector(didReceiveDefaultInstanceIDToken:) + name:kFIRMessagingFCMTokenNotification + object:nil]; + [center addObserver:self + selector:@selector(defaultInstanceIDTokenWasRefreshed:) + name:kFIRMessagingRegistrationTokenRefreshNotification + object:nil]; + [center addObserver:self + selector:@selector(applicationStateChanged) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + [center addObserver:self + selector:@selector(applicationStateChanged) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; +} + +- (void)setupReceiver { + self.receiver = [[FIRMessagingReceiver alloc] init]; + self.receiver.delegate = self; +} + +- (void)setupClient { + self.client = [[FIRMessagingClient alloc] initWithDelegate:self + reachability:self.reachability + rmq2Manager:self.rmq2Manager]; +} + +- (void)setupDataMessageManager { + self.dataMessageManager = + [[FIRMessagingDataMessageManager alloc] initWithDelegate:self.receiver + client:self.client + rmq2Manager:self.rmq2Manager + syncMessageManager:self.syncMessageManager]; + + [self.dataMessageManager refreshDelayedMessages]; + [self.client setDataMessageManager:self.dataMessageManager]; +} + +- (void)setupRmqManager { + self.rmq2Manager = [[FIRMessagingRmqManager alloc] initWithDatabaseName:@"rmq2"]; + [self.rmq2Manager loadRmqId]; +} + +- (void)setupTopics { + _FIRMessagingDevAssert(self.client, @"Invalid nil client before init pubsub."); + self.pubsub = [[FIRMessagingPubSub alloc] initWithClient:self.client]; +} + +- (void)setupSyncMessageManager { + self.syncMessageManager = + [[FIRMessagingSyncMessageManager alloc] initWithRmqManager:self.rmq2Manager]; + + // Delete the expired messages with a delay. We don't want to block startup with a somewhat + // expensive db call. + FIRMessaging_WEAKIFY(self); + dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)); + dispatch_after(time, dispatch_get_main_queue(), ^{ + FIRMessaging_STRONGIFY(self); + [self.syncMessageManager removeExpiredSyncMessages]; + }); +} + +- (void)teardown { + _FIRMessagingDevAssert([NSThread isMainThread], + @"FIRMessaging should be called from main thread only."); + [self.client teardown]; + self.pubsub = nil; + self.syncMessageManager = nil; + self.rmq2Manager = nil; + self.dataMessageManager = nil; + self.client = nil; + self.isClientSetup = NO; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging001, @"Did successfully teardown"); +} + +#pragma mark - Messages + +- (FIRMessagingMessageInfo *)appDidReceiveMessage:(NSDictionary *)message { + if (!message.count) { + return [[FIRMessagingMessageInfo alloc] initWithStatus:FIRMessagingMessageStatusUnknown]; + } + + // For downstream messages that go via MCS we should strip out this key before sending + // the message to the device. + BOOL isOldMessage = NO; + NSString *messageID = message[kFIRMessagingMessageIDKey]; + if ([messageID length]) { + [self.rmq2Manager saveS2dMessageWithRmqId:messageID]; + + BOOL isSyncMessage = [[self class] isAPNSSyncMessage:message]; + if (isSyncMessage) { + isOldMessage = [self.syncMessageManager didReceiveAPNSSyncMessage:message]; + } + } + // Prevent duplicates by keeping a cache of all the logged messages during each session. + // The duplicates only happen when the 3P app calls `appDidReceiveMessage:` along with + // us swizzling their implementation to call the same method implicitly. + if (!isOldMessage && messageID.length) { + isOldMessage = [self.loggedMessageIDs containsObject:messageID]; + if (!isOldMessage) { + [self.loggedMessageIDs addObject:messageID]; + } + } + + if (!isOldMessage) { + [FIRMessagingAnalytics logMessage:message toAnalytics:_analytics]; + [self handleContextManagerMessage:message]; + [self handleIncomingLinkIfNeededFromMessage:message]; + } + return [[FIRMessagingMessageInfo alloc] initWithStatus:FIRMessagingMessageStatusNew]; +} + +- (BOOL)handleContextManagerMessage:(NSDictionary *)message { + if ([FIRMessagingContextManagerService isContextManagerMessage:message]) { + return [FIRMessagingContextManagerService handleContextManagerMessage:message]; + } + return NO; +} + ++ (BOOL)isAPNSSyncMessage:(NSDictionary *)message { + if ([message[kFIRMessagingMessageViaAPNSRootKey] isKindOfClass:[NSDictionary class]]) { + NSDictionary *aps = message[kFIRMessagingMessageViaAPNSRootKey]; + return [aps[kFIRMessagingMessageAPNSContentAvailableKey] boolValue]; + } + return NO; +} + +- (void)handleIncomingLinkIfNeededFromMessage:(NSDictionary *)message { + NSURL *url = [self linkURLFromMessage:message]; + if (url == nil) { + return; + } + if (![NSThread isMainThread]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self handleIncomingLinkIfNeededFromMessage:message]; + + }); + return; + } + UIApplication *application = FIRMessagingUIApplication(); + if (!application) { + return; + } + id appDelegate = application.delegate; + SEL continueUserActivitySelector = + @selector(application:continueUserActivity:restorationHandler:); + SEL openURLWithOptionsSelector = @selector(application:openURL:options:); + SEL openURLWithSourceApplicationSelector = + @selector(application:openURL:sourceApplication:annotation:); + SEL handleOpenURLSelector = @selector(application:handleOpenURL:); + // Due to FIRAAppDelegateProxy swizzling, this selector will most likely get chosen, whether or + // not the actual application has implemented + // |application:continueUserActivity:restorationHandler:|. A warning will be displayed to the user + // if they haven't implemented it. + if ([NSUserActivity class] != nil && + [appDelegate respondsToSelector:continueUserActivitySelector]) { + NSUserActivity *userActivity = + [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb]; + userActivity.webpageURL = url; + [appDelegate application:application + continueUserActivity:userActivity + restorationHandler:^(NSArray * _Nullable restorableObjects) { + // Do nothing, as we don't support the app calling this block + }]; + + } else if ([appDelegate respondsToSelector:openURLWithOptionsSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [appDelegate application:application openURL:url options:@{}]; +#pragma clang diagnostic pop + + // Similarly, |application:openURL:sourceApplication:annotation:| will also always be called, due + // to the default swizzling done by FIRAAppDelegateProxy in Firebase Analytics + } else if ([appDelegate respondsToSelector:openURLWithSourceApplicationSelector]) { +#if TARGET_OS_IOS +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [appDelegate application:application + openURL:url + sourceApplication:FIRMessagingAppIdentifier() + annotation:@{}]; +#pragma clang diagnostic pop +#endif + } else if ([appDelegate respondsToSelector:handleOpenURLSelector]) { +#if TARGET_OS_IOS +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [appDelegate application:application handleOpenURL:url]; +#pragma clang diagnostic pop +#endif + } +} + +- (NSURL *)linkURLFromMessage:(NSDictionary *)message { + NSString *urlString = message[kFIRMessagingMessageLinkKey]; + if (urlString == nil || ![urlString isKindOfClass:[NSString class]] || urlString.length == 0) { + return nil; + } + NSURL *url = [NSURL URLWithString:urlString]; + return url; +} + +#pragma mark - APNS + +- (NSData *)APNSToken { + return self.apnsTokenData; +} + +- (void)setAPNSToken:(NSData *)APNSToken { + [self setAPNSToken:APNSToken type:FIRMessagingAPNSTokenTypeUnknown]; +} + +- (void)setAPNSToken:(NSData *)apnsToken type:(FIRMessagingAPNSTokenType)type { + if ([apnsToken isEqual:self.apnsTokenData]) { + return; + } + self.apnsTokenData = apnsToken; + + // Notify InstanceID that APNS Token has been set. + NSDictionary *userInfo = @{kFIRMessagingAPNSTokenType : @(type)}; + NSNotification *notification = + [NSNotification notificationWithName:kFIRMessagingAPNSTokenNotification + object:[apnsToken copy] + userInfo:userInfo]; + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; +} + +#pragma mark - FCM + +- (BOOL)isAutoInitEnabled { + // Check storage + id isAutoInitEnabledObject = + [_messagingUserDefaults objectForKey:kFIRMessagingUserDefaultsKeyAutoInitEnabled]; + if (isAutoInitEnabledObject) { + return [isAutoInitEnabledObject boolValue]; + } + + // Check Info.plist + isAutoInitEnabledObject = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRMessagingPlistAutoInitEnabled]; + if (isAutoInitEnabledObject) { + return [isAutoInitEnabledObject boolValue]; + } + + // If none of above exists, we default to the global switch that comes from FIRApp. + return [[FIRApp defaultApp] isDataCollectionDefaultEnabled]; +} + +- (void)setAutoInitEnabled:(BOOL)autoInitEnabled { + BOOL isFCMAutoInitEnabled = [self isAutoInitEnabled]; + [_messagingUserDefaults setBool:autoInitEnabled + forKey:kFIRMessagingUserDefaultsKeyAutoInitEnabled]; + [_messagingUserDefaults synchronize]; + if (!isFCMAutoInitEnabled && autoInitEnabled) { + self.defaultFcmToken = self.instanceID.token; + } +} + +- (NSString *)FCMToken { + NSString *token = self.defaultFcmToken; + if (!token) { + // We may not have received it from Instance ID yet (via NSNotification), so extract it directly + token = self.instanceID.token; + } + return token; +} + +- (void)retrieveFCMTokenForSenderID:(nonnull NSString *)senderID + completion:(nonnull FIRMessagingFCMTokenFetchCompletion)completion { + if (!senderID.length) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenFetch, + @"Sender ID not supplied. It is required for a token fetch, " + @"to identify the sender."); + if (completion) { + NSString *description = @"Couldn't fetch token because a Sender ID was not supplied. A valid " + @"Sender ID is required to fetch an FCM token"; + NSError *error = [NSError fcm_errorWithCode:FIRMessagingErrorInvalidRequest + userInfo:@{NSLocalizedDescriptionKey : description}]; + completion(nil, error); + } + return; + } + NSDictionary *options = nil; + if (self.APNSToken) { + options = @{kFIRMessagingFCMTokenFetchAPNSOption : self.APNSToken}; + } else { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeAPNSTokenNotAvailableDuringTokenFetch, + @"APNS device token not set before retrieving FCM Token for Sender ID " + @"'%@'. Notifications to this FCM Token will not be delivered over APNS." + @"Be sure to re-retrieve the FCM token once the APNS device token is " + @"set.", senderID); + } + [self.instanceID tokenWithAuthorizedEntity:senderID + scope:kFIRMessagingDefaultTokenScope + options:options + handler:completion]; +} + +- (void)deleteFCMTokenForSenderID:(nonnull NSString *)senderID + completion:(nonnull FIRMessagingDeleteFCMTokenCompletion)completion { + if (!senderID.length) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenDelete, + @"Sender ID not supplied. It is required to delete an FCM token."); + if (completion) { + NSString *description = @"Couldn't delete token because a Sender ID was not supplied. A " + @"valid Sender ID is required to delete an FCM token"; + NSError *error = [NSError fcm_errorWithCode:FIRMessagingErrorInvalidRequest + userInfo:@{NSLocalizedDescriptionKey : description}]; + completion(error); + } + return; + } + [self.instanceID deleteTokenWithAuthorizedEntity:senderID + scope:kFIRMessagingDefaultTokenScope + handler:completion]; +} + +#pragma mark - FIRMessagingDelegate helper methods +- (void)setDelegate:(id)delegate { + _delegate = delegate; + [self validateDelegateConformsToTokenAvailabilityMethods]; +} + +// Check if the delegate conforms to |didReceiveRegistrationToken:| +// and display a warning to the developer if not. +// NOTE: Once |didReceiveRegistrationToken:| can be made a required method, this +// check can be removed. +- (void)validateDelegateConformsToTokenAvailabilityMethods { + if (self.delegate && + ![self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented, + @"The object %@ does not respond to " + @"-messaging:didReceiveRegistrationToken:. Please implement " + @"-messaging:didReceiveRegistrationToken: to be provided with an FCM " + @"token.", self.delegate.description); + } +} + +- (void)notifyDelegateOfFCMTokenAvailability { + __weak FIRMessaging *weakSelf = self; + if (![NSThread isMainThread]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf notifyDelegateOfFCMTokenAvailability]; + }); + return; + } + if ([self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) { + [self.delegate messaging:self didReceiveRegistrationToken:self.defaultFcmToken]; + } +} + +#pragma mark - Application State Changes + +- (void)applicationStateChanged { + if (self.shouldEstablishDirectChannel) { + [self updateAutomaticClientConnection]; + } +} + +#pragma mark - Direct Channel + +- (void)setShouldEstablishDirectChannel:(BOOL)shouldEstablishDirectChannel { + if (_shouldEstablishDirectChannel == shouldEstablishDirectChannel) { + return; + } + _shouldEstablishDirectChannel = shouldEstablishDirectChannel; + [self updateAutomaticClientConnection]; +} + +- (BOOL)isDirectChannelEstablished { + return self.client.isConnectionActive; +} + +- (BOOL)shouldBeConnectedAutomatically { + // We require a token from Instance ID + NSString *token = self.defaultFcmToken; + // Only on foreground connections + UIApplication *application = FIRMessagingUIApplication(); + if (!application) { + return NO; + } + UIApplicationState applicationState = application.applicationState; + BOOL shouldBeConnected = _shouldEstablishDirectChannel && + (token.length > 0) && + applicationState == UIApplicationStateActive; + return shouldBeConnected; +} + +- (void)updateAutomaticClientConnection { + if (![NSThread isMainThread]) { + // Call this method from the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateAutomaticClientConnection]; + }); + return; + } + BOOL shouldBeConnected = [self shouldBeConnectedAutomatically]; + if (shouldBeConnected && !self.client.isConnected) { + [self.client connectWithHandler:^(NSError *error) { + if (!error) { + // It means we connected. Fire connection change notification + [self notifyOfDirectChannelConnectionChange]; + } else { + FIRMessagingLoggerError(kFIRMessagingMessageCodeDirectChannelConnectionFailed, + @"Failed to connect to direct channel, error: %@\n", error); + } + }]; + } else if (!shouldBeConnected && self.client.isConnected) { + [self.client disconnect]; + [self notifyOfDirectChannelConnectionChange]; + } +} + +- (void)notifyOfDirectChannelConnectionChange { + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:FIRMessagingConnectionStateChangedNotification object:self]; +} + +#pragma mark - Topics + ++ (NSString *)normalizeTopic:(NSString *)topic { + if (!topic.length) { + return nil; + } + if (![FIRMessagingPubSub hasTopicsPrefix:topic]) { + topic = [FIRMessagingPubSub addPrefixToTopic:topic]; + } + if ([FIRMessagingPubSub isValidTopicWithPrefix:topic]) { + return [topic copy]; + } + return nil; +} + +- (void)subscribeToTopic:(NSString *)topic { + [self subscribeToTopic:topic completion:nil]; +} + +- (void)subscribeToTopic:(NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion { + if ([FIRMessagingPubSub hasTopicsPrefix:topic]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTopicFormatIsDeprecated, + @"Format '%@' is deprecated. Only '%@' should be used in " + @"subscribeToTopic.", + topic, [FIRMessagingPubSub removePrefixFromTopic:topic]); + } + if (!self.defaultFcmToken.length) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeMessaging010, + @"The subscription operation is suspended because you don't have a " + @"token. The operation will resume once you get an FCM token."); + } + NSString *normalizeTopic = [[self class] normalizeTopic:topic]; + if (normalizeTopic.length) { + [self.pubsub subscribeToTopic:normalizeTopic handler:completion]; + return; + } + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging009, + @"Cannot parse topic name %@. Will not subscribe.", topic); + if (completion) { + completion([NSError fcm_errorWithCode:FIRMessagingErrorInvalidTopicName userInfo:nil]); + } +} + +- (void)unsubscribeFromTopic:(NSString *)topic { + [self unsubscribeFromTopic:topic completion:nil]; +} + +- (void)unsubscribeFromTopic:(NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion { + if ([FIRMessagingPubSub hasTopicsPrefix:topic]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTopicFormatIsDeprecated, + @"Format '%@' is deprecated. Only '%@' should be used in " + @"unsubscribeFromTopic.", + topic, [FIRMessagingPubSub removePrefixFromTopic:topic]); + } + if (!self.defaultFcmToken.length) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeMessaging012, + @"The unsubscription operation is suspended because you don't have a " + @"token. The operation will resume once you get an FCM token."); + } + NSString *normalizeTopic = [[self class] normalizeTopic:topic]; + if (normalizeTopic.length) { + [self.pubsub unsubscribeFromTopic:normalizeTopic handler:completion]; + return; + } + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging011, + @"Cannot parse topic name %@. Will not unsubscribe.", topic); + if (completion) { + completion([NSError fcm_errorWithCode:FIRMessagingErrorInvalidTopicName userInfo:nil]); + } +} + +#pragma mark - Send + +- (void)sendMessage:(NSDictionary *)message + to:(NSString *)to + withMessageID:(NSString *)messageID + timeToLive:(int64_t)ttl { + _FIRMessagingDevAssert([to length] != 0, @"Invalid receiver id for FIRMessaging-message"); + + NSMutableDictionary *fcmMessage = [[self class] createFIRMessagingMessageWithMessage:message + to:to + withID:messageID + timeToLive:ttl + delay:0]; + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeMessaging013, @"Sending message: %@ with id: %@", + message, messageID); + [self.dataMessageManager sendDataMessageStanza:fcmMessage]; +} + ++ (NSMutableDictionary *)createFIRMessagingMessageWithMessage:(NSDictionary *)message + to:(NSString *)to + withID:(NSString *)msgID + timeToLive:(int64_t)ttl + delay:(int)delay { + NSMutableDictionary *fcmMessage = [NSMutableDictionary dictionary]; + fcmMessage[kFIRMessagingSendTo] = [to copy]; + fcmMessage[kFIRMessagingSendMessageID] = msgID ? [msgID copy] : @""; + fcmMessage[kFIRMessagingSendTTL] = @(ttl); + fcmMessage[kFIRMessagingSendDelay] = @(delay); + fcmMessage[KFIRMessagingSendMessageAppData] = + [NSMutableDictionary dictionaryWithDictionary:message]; + return fcmMessage; +} + +#pragma mark - IID dependencies + ++ (NSString *)FIRMessagingSDKVersion { + return FIRMessagingCurrentLibraryVersion(); +} + ++ (NSString *)FIRMessagingSDKCurrentLocale { + return [self currentLocale]; +} + +#pragma mark - FIRMessagingReceiverDelegate + +- (void)receiver:(FIRMessagingReceiver *)receiver + receivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { + if ([self.delegate respondsToSelector:@selector(messaging:didReceiveMessage:)]) { + [self appDidReceiveMessage:remoteMessage.appData]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [self.delegate messaging:self didReceiveMessage:remoteMessage]; +#pragma pop + } else { + // Delegate methods weren't implemented, so messages are being dropped, log a warning + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented, + @"FIRMessaging received data-message, but FIRMessagingDelegate's" + @"-messaging:didReceiveMessage: not implemented"); + } +} + +#pragma mark - GULReachabilityDelegate + +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + [self onNetworkStatusChanged]; +} + +#pragma mark - Network + +- (void)onNetworkStatusChanged { + if (![self.client isConnected] && [self isNetworkAvailable]) { + if (self.client.shouldStayConnected) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging014, + @"Attempting to establish direct channel."); + [self.client retryConnectionImmediately:YES]; + } + [self.pubsub scheduleSync:YES]; + } +} + +- (BOOL)isNetworkAvailable { + GULReachabilityStatus status = self.reachability.reachabilityStatus; + return (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); +} + +- (FIRMessagingNetworkStatus)networkType { + GULReachabilityStatus status = self.reachability.reachabilityStatus; + if (![self isNetworkAvailable]) { + return kFIRMessagingReachabilityNotReachable; + } else if (status == kGULReachabilityViaCellular) { + return kFIRMessagingReachabilityReachableViaWWAN; + } else { + return kFIRMessagingReachabilityReachableViaWiFi; + } +} + +#pragma mark - Notifications + +- (void)didReceiveDefaultInstanceIDToken:(NSNotification *)notification { + if (notification.object && ![notification.object isKindOfClass:[NSString class]]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging015, + @"Invalid default FCM token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSString *oldToken = self.defaultFcmToken; + self.defaultFcmToken = [(NSString *)notification.object copy]; + if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) { + [self notifyDelegateOfFCMTokenAvailability]; + } + [self.pubsub scheduleSync:YES]; + if (self.shouldEstablishDirectChannel) { + [self updateAutomaticClientConnection]; + } +} + +- (void)defaultInstanceIDTokenWasRefreshed:(NSNotification *)notification { + // Retrieve the Instance ID default token, and if it is non-nil, post it + NSString *token = self.instanceID.token; + // Sometimes Instance ID doesn't yet have a token, so wait until the default + // token is fetched, and then notify. This ensures that this token should not + // be nil when the developer accesses it. + if (token != nil) { + NSString *oldToken = self.defaultFcmToken; + self.defaultFcmToken = [token copy]; + if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) { + [self notifyDelegateOfFCMTokenAvailability]; + } + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:FIRMessagingRegistrationTokenRefreshedNotification object:nil]; + } +} + +#pragma mark - Application Support Directory + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSString *)pathForSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), + NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[dirPath, subDirectoryName]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging017, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeMessaging018, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + +#pragma mark - Locales + ++ (NSString *)currentLocale { + NSArray *locales = [self firebaseLocales]; + NSArray *preferredLocalizations = + [NSBundle preferredLocalizationsFromArray:locales + forPreferences:[NSLocale preferredLanguages]]; + NSString *legalDocsLanguage = [preferredLocalizations firstObject]; + // Use en as the default language + return legalDocsLanguage ? legalDocsLanguage : @"en"; +} + ++ (NSArray *)firebaseLocales { + NSMutableArray *locales = [NSMutableArray array]; + NSDictionary *localesMap = [self firebaselocalesMap]; + for (NSString *key in localesMap) { + [locales addObjectsFromArray:localesMap[key]]; + } + return locales; +} + ++ (NSDictionary *)firebaselocalesMap { + return @{ + // Albanian + @"sq" : @[ @"sq_AL" ], + // Belarusian + @"be" : @[ @"be_BY" ], + // Bulgarian + @"bg" : @[ @"bg_BG" ], + // Catalan + @"ca" : @[ @"ca", @"ca_ES" ], + // Croatian + @"hr" : @[ @"hr", @"hr_HR" ], + // Czech + @"cs" : @[ @"cs", @"cs_CZ" ], + // Danish + @"da" : @[ @"da", @"da_DK" ], + // Estonian + @"et" : @[ @"et_EE" ], + // Finnish + @"fi" : @[ @"fi", @"fi_FI" ], + // Hebrew + @"he" : @[ @"he", @"iw_IL" ], + // Hindi + @"hi" : @[ @"hi_IN" ], + // Hungarian + @"hu" : @[ @"hu", @"hu_HU" ], + // Icelandic + @"is" : @[ @"is_IS" ], + // Indonesian + @"id" : @[ @"id", @"in_ID", @"id_ID" ], + // Irish + @"ga" : @[ @"ga_IE" ], + // Korean + @"ko" : @[ @"ko", @"ko_KR", @"ko-KR" ], + // Latvian + @"lv" : @[ @"lv_LV" ], + // Lithuanian + @"lt" : @[ @"lt_LT" ], + // Macedonian + @"mk" : @[ @"mk_MK" ], + // Malay + @"ms" : @[ @"ms_MY" ], + // Maltese + @"ms" : @[ @"mt_MT" ], + // Polish + @"pl" : @[ @"pl", @"pl_PL", @"pl-PL" ], + // Romanian + @"ro" : @[ @"ro", @"ro_RO" ], + // Russian + @"ru" : @[ @"ru_RU", @"ru", @"ru_BY", @"ru_KZ", @"ru-RU" ], + // Slovak + @"sk" : @[ @"sk", @"sk_SK" ], + // Slovenian + @"sl" : @[ @"sl_SI" ], + // Swedish + @"sv" : @[ @"sv", @"sv_SE", @"sv-SE" ], + // Turkish + @"tr" : @[ @"tr", @"tr-TR", @"tr_TR" ], + // Ukrainian + @"uk" : @[ @"uk", @"uk_UA" ], + // Vietnamese + @"vi" : @[ @"vi", @"vi_VN" ], + // The following are groups of locales or locales that sub-divide a + // language). + // Arabic + @"ar" : @[ + @"ar", + @"ar_DZ", + @"ar_BH", + @"ar_EG", + @"ar_IQ", + @"ar_JO", + @"ar_KW", + @"ar_LB", + @"ar_LY", + @"ar_MA", + @"ar_OM", + @"ar_QA", + @"ar_SA", + @"ar_SD", + @"ar_SY", + @"ar_TN", + @"ar_AE", + @"ar_YE", + @"ar_GB", + @"ar-IQ", + @"ar_US" + ], + // Simplified Chinese + @"zh_Hans" : @[ @"zh_CN", @"zh_SG", @"zh-Hans" ], + // Traditional Chinese + @"zh_Hant" : @[ @"zh_HK", @"zh_TW", @"zh-Hant", @"zh-HK", @"zh-TW" ], + // Dutch + @"nl" : @[ @"nl", @"nl_BE", @"nl_NL", @"nl-NL" ], + // English + @"en" : @[ + @"en", + @"en_AU", + @"en_CA", + @"en_IN", + @"en_IE", + @"en_MT", + @"en_NZ", + @"en_PH", + @"en_SG", + @"en_ZA", + @"en_GB", + @"en_US", + @"en_AE", + @"en-AE", + @"en_AS", + @"en-AU", + @"en_BD", + @"en-CA", + @"en_EG", + @"en_ES", + @"en_GB", + @"en-GB", + @"en_HK", + @"en_ID", + @"en-IN", + @"en_NG", + @"en-PH", + @"en_PK", + @"en-SG", + @"en-US" + ], + // French + + @"fr" : @[ + @"fr", + @"fr_BE", + @"fr_CA", + @"fr_FR", + @"fr_LU", + @"fr_CH", + @"fr-CA", + @"fr-FR", + @"fr_MA" + ], + // German + @"de" : @[ @"de", @"de_AT", @"de_DE", @"de_LU", @"de_CH", @"de-DE" ], + // Greek + @"el" : @[ @"el", @"el_CY", @"el_GR" ], + // Italian + @"it" : @[ @"it", @"it_IT", @"it_CH", @"it-IT" ], + // Japanese + @"ja" : @[ @"ja", @"ja_JP", @"ja_JP_JP", @"ja-JP" ], + // Norwegian + @"no" : @[ @"nb", @"no_NO", @"no_NO_NY", @"nb_NO" ], + // Brazilian Portuguese + @"pt_BR" : @[ @"pt_BR", @"pt-BR" ], + // European Portuguese + @"pt_PT" : @[ @"pt", @"pt_PT", @"pt-PT" ], + // Serbian + @"sr" : @[ + @"sr_BA", + @"sr_ME", + @"sr_RS", + @"sr_Latn_BA", + @"sr_Latn_ME", + @"sr_Latn_RS" + ], + // European Spanish + @"es_ES" : @[ @"es", @"es_ES", @"es-ES" ], + // Mexican Spanish + @"es_MX" : @[ @"es-MX", @"es_MX", @"es_US", @"es-US" ], + // Latin American Spanish + @"es_419" : @[ + @"es_AR", + @"es_BO", + @"es_CL", + @"es_CO", + @"es_CR", + @"es_DO", + @"es_EC", + @"es_SV", + @"es_GT", + @"es_HN", + @"es_NI", + @"es_PA", + @"es_PY", + @"es_PE", + @"es_PR", + @"es_UY", + @"es_VE", + @"es-AR", + @"es-CL", + @"es-CO" + ], + // Thai + @"th" : @[ @"th", @"th_TH", @"th_TH_TH" ], + }; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.h new file mode 100644 index 0000000..13bfab5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides integration between FIRMessaging and Analytics. + * + * All Analytics dependencies should be kept in this class, and missing dependencies should be + * handled gracefully. + * + */ +@interface FIRMessagingAnalytics : NSObject + +/** + * Determine whether a notification has the properties to be loggable to Analytics. + * If so, send the notification. + * @param notification The notification payload from APNs + * @param analytics The class to be used as the receiver of the logging method + */ + ++ (void)logMessage:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.m new file mode 100644 index 0000000..42124be --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingAnalytics.m @@ -0,0 +1,225 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRMessagingAnalytics.h" +#import "FIRMessagingLogger.h" + +#import +#import +#import + +static NSString *const kLogTag = @"FIRMessagingAnalytics"; + +// aps Key +static NSString *const kApsKey = @"aps"; +static NSString *const kApsAlertKey = @"alert"; +static NSString *const kApsSoundKey = @"sound"; +static NSString *const kApsBadgeKey = @"badge"; +static NSString *const kApsContentAvailableKey = @"badge"; + +// Data Key +static NSString *const kDataKey = @"data"; + +// Messaging From Key +static NSString *const kFIRMessagingFromKey = @"from"; + +static NSString *const kFIRParameterLabel = @"label"; + +static NSString *const kReengagementSource = @"Firebase"; +static NSString *const kReengagementMedium = @"notification"; + +// Analytics +static NSString *const kAnalyticsEnabled = @"google.c.a." @"e"; +static NSString *const kAnalyticsComposerIdentifier = @"google.c.a." @"c_id"; +static NSString *const kAnalyticsComposerLabel = @"google.c.a." @"c_l"; +static NSString *const kAnalyticsMessageLabel = @"google.c.a." @"m_l"; +static NSString *const kAnalyticsMessageTimestamp = @"google.c.a." @"ts"; +static NSString *const kAnalyticsMessageUseDeviceTime = @"google.c.a." @"udt"; +static NSString *const kAnalyticsTrackConversions = @"google.c.a." @"tc"; + +@implementation FIRMessagingAnalytics + ++ (BOOL)canLogNotification:(NSDictionary *)notification { + if (!notification.count) { + // Payload is empty + return NO; + } + NSString *isAnalyticsLoggingEnabled = notification[kAnalyticsEnabled]; + if (![isAnalyticsLoggingEnabled isKindOfClass:[NSString class]] || + ![isAnalyticsLoggingEnabled isEqualToString:@"1"]) { + // Analytics logging is not enabled + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics001, + @"Analytics logging is disabled. Do not log event."); + return NO; + } + return YES; +} + ++ (void)logOpenNotification:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + [self logUserPropertyForConversionTracking:notification toAnalytics:analytics]; + [self logEvent:kFIRIEventNotificationOpen +withNotification:notification + toAnalytics:analytics]; +} + ++ (void)logForegroundNotification:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + [self logEvent:kFIRIEventNotificationForeground +withNotification:notification + toAnalytics:analytics]; +} + ++ (void)logEvent:(NSString *)event +withNotification:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + if (!event.length) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalyticsInvalidEvent, + @"Can't log analytics with empty event."); + return; + } + NSMutableDictionary *params = [self paramsForEvent:event withNotification:notification]; + + [analytics logEventWithOrigin:@"fcm" name:event parameters:params]; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics005, + @"%@: Sending event: %@ params: %@", kLogTag, event, params); +} + ++ (NSMutableDictionary *)paramsForEvent:(NSString *)event + withNotification:(NSDictionary *)notification { + NSDictionary *analyticsDataMap = notification; + if (!analyticsDataMap.count) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics000, + @"No data found in notification. Will not log any analytics events."); + return nil; + } + + if (![self canLogNotification:analyticsDataMap]) { + return nil; + } + + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + NSString *composerIdentifier = analyticsDataMap[kAnalyticsComposerIdentifier]; + if ([composerIdentifier isKindOfClass:[NSString class]] && composerIdentifier.length) { + params[kFIRIParameterMessageIdentifier] = [composerIdentifier copy]; + } + + NSString *composerLabel = analyticsDataMap[kAnalyticsComposerLabel]; + if ([composerLabel isKindOfClass:[NSString class]] && composerLabel.length) { + params[kFIRIParameterMessageName] = [composerLabel copy]; + } + + NSString *messageLabel = analyticsDataMap[kAnalyticsMessageLabel]; + if ([messageLabel isKindOfClass:[NSString class]] && messageLabel.length) { + params[kFIRParameterLabel] = [messageLabel copy]; + } + + NSString *from = analyticsDataMap[kFIRMessagingFromKey]; + if ([from isKindOfClass:[NSString class]] && [from containsString:@"/topics/"]) { + params[kFIRIParameterTopic] = [from copy]; + } + + id timestamp = analyticsDataMap[kAnalyticsMessageTimestamp]; + if ([timestamp respondsToSelector:@selector(longLongValue)]) { + int64_t timestampValue = [timestamp longLongValue]; + if (timestampValue != 0) { + params[kFIRIParameterMessageTime] = @(timestampValue); + } + } + + if (analyticsDataMap[kAnalyticsMessageUseDeviceTime]) { + params[kFIRIParameterMessageDeviceTime] = analyticsDataMap[kAnalyticsMessageUseDeviceTime]; + } + + return params; +} + ++ (void)logUserPropertyForConversionTracking:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + NSInteger shouldTrackConversions = [notification[kAnalyticsTrackConversions] integerValue]; + if (shouldTrackConversions != 1) { + return; + } + + NSString *composerIdentifier = notification[kAnalyticsComposerIdentifier]; + if ([composerIdentifier isKindOfClass:[NSString class]] && composerIdentifier.length) { + // Set user property for event. + [analytics setUserPropertyWithOrigin:@"fcm" + name:kFIRIUserPropertyLastNotification + value:composerIdentifier]; + + // Set the re-engagement attribution properties. + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:3]; + params[kFIRIParameterSource] = kReengagementSource; + params[kFIRIParameterMedium] = kReengagementMedium; + params[kFIRIParameterCampaign] = composerIdentifier; + [analytics logEventWithOrigin:@"fcm" name:kFIRIEventFirebaseCampaign parameters:params]; + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics003, + @"%@: Sending event: %@ params: %@", kLogTag, + kFIRIEventFirebaseCampaign, params); + + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics004, + @"%@: Failed to set user property: %@ value: %@", kLogTag, + kFIRIUserPropertyLastNotification, composerIdentifier); + } +} + ++ (void)logMessage:(NSDictionary *)notification + toAnalytics:(id _Nullable)analytics { + if (![self canLogNotification:notification]) { + return; + } + + UIApplication *application = [self currentUIApplication]; + if (!application) { + return; + } + UIApplicationState applicationState = application.applicationState; + switch (applicationState) { + case UIApplicationStateInactive: + // App was either in background(suspended) or inactive and user tapped on a display + // notification. + [self logOpenNotification:notification toAnalytics:analytics]; + break; + + case UIApplicationStateActive: + // App was in foreground when it received the notification. + [self logForegroundNotification:notification toAnalytics:analytics]; + break; + + default: + // Only a silent notification (i.e. 'content-available' is true) can be received while the app + // is in the background. These messages aren't loggable anyway. + break; + } +} + ++ (UIApplication *)currentUIApplication { + Class applicationClass = nil; + if (![GULAppEnvironmentUtil isAppExtension]) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + return [applicationClass sharedApplication]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.h new file mode 100644 index 0000000..d7c3451 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Register the device with Checkin Service and get back the `authID`, `secret token` etc. for the + * client. Checkin results are cached and periodically refreshed to + * prevent them from being stale. Each client needs to register with checkin before registering + * with FIRMessaging. + */ +@interface FIRMessagingCheckinService : NSObject + +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; +@property(nonatomic, readonly, strong) NSString *versionInfo; +@property(nonatomic, readonly, assign) BOOL hasValidCheckinInfo; + +/** + * Verify if valid checkin preferences have been loaded in memory. + * + * @return YES if valid checkin preferences exist in memory else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Try to load prefetched checkin preferences from the cache. This supports the use case where + * InstanceID library has already obtained a valid checkin and we should be using that. + * + * This should be used as a last gasp effort to retreive any cached checkin preferences before + * hitting the FIRMessaging backend to retrieve new preferences. + * + * Note this is only required because InstanceID and FIRMessaging both require checkin preferences which + * need to be synced with each other. + * + * @return YES if successfully loaded cached checkin preferences into memory else NO. + */ +- (BOOL)tryToLoadPrefetchedCheckinPreferences; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.m new file mode 100644 index 0000000..9dad847 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCheckinService.m @@ -0,0 +1,132 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingCheckinService.h" + +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +@interface FIRMessagingCheckinService () + +// This property is of type FIRInstanceIDCheckinPreferences, if InstanceID was directly linkable +@property(nonatomic, readwrite, strong) id checkinPreferences; + +@end + +@implementation FIRMessagingCheckinService; + +#pragma mark - Reflection-Based Getter Functions + +// Encapsulates the -hasValidCheckinInfo method of FIRInstanceIDCheckinPreferences +BOOL FIRMessagingCheckinService_hasValidCheckinInfo(id checkinPreferences) { + SEL hasValidCheckinInfoSelector = NSSelectorFromString(@"hasValidCheckinInfo"); + if (![checkinPreferences respondsToSelector:hasValidCheckinInfoSelector]) { + // Can't check hasValidCheckinInfo + return NO; + } + + // Since hasValidCheckinInfo returns a BOOL, use NSInvocation + NSMethodSignature *methodSignature = + [[checkinPreferences class] instanceMethodSignatureForSelector:hasValidCheckinInfoSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + invocation.selector = hasValidCheckinInfoSelector; + invocation.target = checkinPreferences; + [invocation invoke]; + BOOL returnValue; + [invocation getReturnValue:&returnValue]; + return returnValue; +} + +// Returns a non-scalar (id) object based on the property name +id FIRMessagingCheckinService_propertyNamed(id checkinPreferences, NSString *propertyName) { + SEL propertyGetterSelector = NSSelectorFromString(propertyName); + if ([checkinPreferences respondsToSelector:propertyGetterSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + return [checkinPreferences performSelector:propertyGetterSelector]; +#pragma clang diagnostic pop + } + return nil; +} + +#pragma mark - Methods + +- (BOOL)tryToLoadPrefetchedCheckinPreferences { + Class instanceIDClass = NSClassFromString(@"FIRInstanceID"); + if (!instanceIDClass) { + // InstanceID is not linked + return NO; + } + + // [FIRInstanceID instanceID] + SEL instanceIDSelector = NSSelectorFromString(@"instanceID"); + if (![instanceIDClass respondsToSelector:instanceIDSelector]) { + return NO; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id instanceID = [instanceIDClass performSelector:instanceIDSelector]; +#pragma clang diagnostic pop + if (!instanceID) { + // Instance ID singleton not available + return NO; + } + + // [[FIRInstanceID instanceID] cachedCheckinPreferences] + SEL cachedCheckinPrefsSelector = NSSelectorFromString(@"cachedCheckinPreferences"); + if (![instanceID respondsToSelector:cachedCheckinPrefsSelector]) { + // cachedCheckinPreferences is not accessible + return NO; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id checkinPreferences = [instanceID performSelector:cachedCheckinPrefsSelector]; +#pragma clang diagnostic pop + if (!checkinPreferences) { + // No cached checkin prefs + return NO; + } + + BOOL hasValidInfo = FIRMessagingCheckinService_hasValidCheckinInfo(checkinPreferences); + if (hasValidInfo) { + self.checkinPreferences = checkinPreferences; + } + return hasValidInfo; +} + +#pragma mark - API + +- (NSString *)deviceAuthID { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"deviceID"); +} + +- (NSString *)secretToken { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"secretToken"); +} + +- (NSString *)versionInfo { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"versionInfo"); +} + +- (NSString *)digest { + return FIRMessagingCheckinService_propertyNamed(self.checkinPreferences, @"digest"); +} + +- (BOOL)hasValidCheckinInfo { + return FIRMessagingCheckinService_hasValidCheckinInfo(self.checkinPreferences); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.h new file mode 100644 index 0000000..98337a3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" + +@class GULReachabilityChecker; +@class GPBMessage; + +@class FIRMessagingConnection; +@class FIRMessagingDataMessageManager; +@class FIRMessagingRmqManager; + +/** + * Callback to handle MCS connection requests. + * + * @param error The error object if any while trying to connect with MCS else nil. + */ +typedef void(^FIRMessagingConnectCompletionHandler)(NSError *error); + +@protocol FIRMessagingClientDelegate + +@end + +/** + * The client handles the subscribe/unsubscribe for an unregistered senderID + * and device. It also manages the FIRMessaging data connection, the exponential backoff + * algorithm in case of registration failures, sign in failures and unregister + * failures. It also handles the reconnect logic if the FIRMessaging connection is + * broken off by some error during an active session. + */ +@interface FIRMessagingClient : NSObject + +@property(nonatomic, readonly, strong) FIRMessagingConnection *connection; +@property(nonatomic, readwrite, weak) FIRMessagingDataMessageManager *dataMessageManager; + +// Designated initializer +- (instancetype)initWithDelegate:(id)delegate + reachability:(GULReachabilityChecker *)reachability + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager; + +- (void)teardown; + +- (void)cancelAllRequests; + +#pragma mark - FIRMessaging subscribe + +/** + * Update the subscription associated with the given token and topic. + * + * For a to-be-created subscription we check if the client is already + * subscribed to the topic or not. If subscribed we should have the + * subscriptionID in the cache and we return from there itself, else we call + * the FIRMessaging backend to create a new subscription for the topic for this client. + * + * For delete subscription requests we delete the stored subscription in the + * client and then invoke the FIRMessaging backend to delete the existing subscription + * completely. + * + * @param token The token associated with the device. + * @param topic The topic for which the subscription should be updated. + * @param options The options to be passed in to the subscription request. + * @param shouldDelete If YES this would delete the subscription from the cache + * and also let the FIRMessaging backend know that we need to delete + * the subscriptionID associated with this topic. + * If NO we try to create a new subscription for the given + * token and topic. + * @param handler The handler to invoke once the subscription request + * finishes. + */ +- (void)updateSubscriptionWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler; + +#pragma mark - MCS Connection + +/** + * Create a MCS connection. + * + * @param handler The handler to be invokend once the connection is setup. If + * setting up the connection fails we invoke the handler with + * an appropriate error object. + */ +- (void)connectWithHandler:(FIRMessagingConnectCompletionHandler)handler; + +/** + * Disconnect the current MCS connection. If there is no valid connection this + * should be a NO-OP. + */ +- (void)disconnect; + +#pragma mark - MCS Connection State + +/** + * If we are connected to MCS or not. This doesn't take into account the fact if + * the client has been signed in(verified) by MCS. + * + * @return YES if we are signed in or connecting and trying to sign-in else NO. + */ +@property(nonatomic, readonly) BOOL isConnected; + +/** + * If we have an active MCS connection + * + * @return YES if we have an active MCS connection else NO. + */ +@property(nonatomic, readonly) BOOL isConnectionActive; + +/** + * If we should be connected to MCS + * + * @return YES if we have attempted a connection and not requested to disconect. + */ +@property(nonatomic, readonly) BOOL shouldStayConnected; + +/** + * Schedule a retry to connect to MCS. If `immediately` is `YES` try to + * schedule a retry now else retry with some delay. + * + * @param immediately Should retry right now. + */ +- (void)retryConnectionImmediately:(BOOL)immediately; + +#pragma mark - Messages + +/** + * Send a message over the MCS connection. + * + * @param message Message to be sent. + */ +- (void)sendMessage:(GPBMessage *)message; + +/** + * Send message if we have an active MCS connection. If not cache the message + * for this session and in case we are able to re-establish the connection try + * again else drop it. This should only be used for TTL=0 messages for now. + * + * @param message Message to be sent. + */ +- (void)sendOnConnectOrDrop:(GPBMessage *)message; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.m new file mode 100644 index 0000000..9d8c558 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingClient.m @@ -0,0 +1,506 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingClient.h" + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingConnection.h" +#import "FIRMessagingConstants.h" +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingRegistrar.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingTopicsCommon.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +static const NSTimeInterval kConnectTimeoutInterval = 40.0; +static const NSTimeInterval kReconnectDelayInSeconds = 2 * 60; // 2 minutes + +static const NSUInteger kMaxRetryExponent = 10; // 2^10 = 1024 seconds ~= 17 minutes + +static NSString *const kFIRMessagingMCSServerHost = @"mtalk.google.com"; +static NSUInteger const kFIRMessagingMCSServerPort = 5228; + +// register device with checkin +typedef void(^FIRMessagingRegisterDeviceHandler)(NSError *error); + +static NSString *FIRMessagingServerHost() { + static NSString *serverHost = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *environment = [[NSProcessInfo processInfo] environment]; + NSString *customServerHostAndPort = environment[@"FCM_MCS_HOST"]; + NSString *host = [customServerHostAndPort componentsSeparatedByString:@":"].firstObject; + if (host) { + serverHost = host; + } else { + serverHost = kFIRMessagingMCSServerHost; + } + }); + return serverHost; +} + +static NSUInteger FIRMessagingServerPort() { + static NSUInteger serverPort = kFIRMessagingMCSServerPort; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *environment = [[NSProcessInfo processInfo] environment]; + NSString *customServerHostAndPort = environment[@"FCM_MCS_HOST"]; + NSArray *components = [customServerHostAndPort componentsSeparatedByString:@":"]; + NSUInteger port = (NSUInteger)[components.lastObject integerValue]; + if (port != 0) { + serverPort = port; + } + }); + return serverPort; +} + +@interface FIRMessagingClient () + +@property(nonatomic, readwrite, weak) id clientDelegate; +@property(nonatomic, readwrite, strong) FIRMessagingConnection *connection; +@property(nonatomic, readwrite, strong) FIRMessagingRegistrar *registrar; + +@property(nonatomic, readwrite, strong) NSString *senderId; + +// FIRMessagingService owns these instances +@property(nonatomic, readwrite, weak) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, weak) GULReachabilityChecker *reachability; + +@property(nonatomic, readwrite, assign) int64_t lastConnectedTimestamp; +@property(nonatomic, readwrite, assign) int64_t lastDisconnectedTimestamp; +@property(nonatomic, readwrite, assign) NSUInteger connectRetryCount; + +// Should we stay connected to MCS or not. Should be YES throughout the lifetime +// of a MCS connection. If set to NO it signifies that an existing MCS connection +// should be disconnected. +@property(nonatomic, readwrite, assign) BOOL stayConnected; +@property(nonatomic, readwrite, assign) NSTimeInterval connectionTimeoutInterval; + +// Used if the MCS connection suddenly breaksdown in the middle and we want to reconnect +// with some permissible delay we schedule a reconnect and set it to YES and when it's +// scheduled this will be set back to NO. +@property(nonatomic, readwrite, assign) BOOL didScheduleReconnect; + +// handlers +@property(nonatomic, readwrite, copy) FIRMessagingConnectCompletionHandler connectHandler; + +@end + +@implementation FIRMessagingClient + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithDelegate:(id)delegate + reachability:(GULReachabilityChecker *)reachability + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager { + self = [super init]; + if (self) { + _reachability = reachability; + _clientDelegate = delegate; + _rmq2Manager = rmq2Manager; + _registrar = [[FIRMessagingRegistrar alloc] init]; + _connectionTimeoutInterval = kConnectTimeoutInterval; + // Listen for checkin fetch notifications, as connecting to MCS may have failed due to + // missing checkin info (while it was being fetched). + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(checkinFetched:) + name:kFIRMessagingCheckinFetchedNotification + object:nil]; + } + return self; +} + +- (void)teardown { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient000, @""); + self.stayConnected = NO; + + // Clear all the handlers + self.connectHandler = nil; + + [self.connection teardown]; + + // Stop all subscription requests + [self.registrar cancelAllRequests]; + + _FIRMessagingDevAssert(self.connection.state == kFIRMessagingConnectionNotConnected, @"Did not disconnect"); + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)cancelAllRequests { + // Stop any checkin requests or any subscription requests + [self.registrar cancelAllRequests]; + + // Stop any future connection requests to MCS + if (self.stayConnected && self.isConnected && !self.isConnectionActive) { + self.stayConnected = NO; + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + } +} + +#pragma mark - FIRMessaging subscribe + +- (void)updateSubscriptionWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler { + + _FIRMessagingDevAssert(handler != nil, @"Invalid handler to FIRMessaging subscribe"); + + FIRMessagingTopicOperationCompletion completion = ^void(NSError *error) { + if (error) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeClient001, @"Failed to subscribe to topic %@", + error); + } else { + if (shouldDelete) { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient002, + @"Successfully unsubscribed from topic %@", topic); + } else { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient003, + @"Successfully subscribed to topic %@", topic); + } + } + handler(error); + }; + + [self.registrar updateSubscriptionToTopic:topic + withToken:token + options:options + shouldDelete:shouldDelete + handler:completion]; +} + +#pragma mark - MCS Connection + +- (BOOL)isConnected { + return self.stayConnected && self.connection.state != kFIRMessagingConnectionNotConnected; +} + +- (BOOL)isConnectionActive { + return self.stayConnected && self.connection.state == kFIRMessagingConnectionSignedIn; +} + +- (BOOL)shouldStayConnected { + return self.stayConnected; +} + +- (void)retryConnectionImmediately:(BOOL)immediately { + // Do not connect to an invalid host or an invalid port + if (!self.stayConnected || !self.connection.host || self.connection.port == 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient004, + @"FIRMessaging connection will not reconnect to MCS. " + @"Stay connected: %d", + self.stayConnected); + return; + } + if (self.isConnectionActive) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient005, + @"FIRMessaging Connection skip retry, active"); + // already connected and logged in. + // Heartbeat alarm is set and will force close the connection + return; + } + if (self.isConnected) { + // already connected and logged in. + // Heartbeat alarm is set and will force close the connection + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient006, + @"FIRMessaging Connection skip retry, connected"); + return; + } + + if (immediately) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient007, + @"Try to connect to MCS immediately"); + [self tryToConnect]; + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient008, @"Try to connect to MCS lazily"); + // Avoid all the other logic that we have in other clients, since this would always happen + // when the app is in the foreground and since the FIRMessaging connection isn't shared with any other + // app we can be more aggressive in reconnections + if (!self.didScheduleReconnect) { + FIRMessaging_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(kReconnectDelayInSeconds * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRMessaging_STRONGIFY(self); + self.didScheduleReconnect = NO; + [self tryToConnect]; + }); + + self.didScheduleReconnect = YES; + } + } +} + +- (void)connectWithHandler:(FIRMessagingConnectCompletionHandler)handler { + if (self.isConnected) { + NSError *error = [NSError fcm_errorWithCode:kFIRMessagingErrorCodeAlreadyConnected + userInfo:@{ + NSLocalizedFailureReasonErrorKey: @"FIRMessaging is already connected", + }]; + handler(error); + return; + } + self.lastDisconnectedTimestamp = FIRMessagingCurrentTimestampInMilliseconds(); + self.connectHandler = handler; + [self connect]; +} + +- (void)connect { + // reset retry counts + self.connectRetryCount = 0; + + if (self.isConnected) { + return; + } + + self.stayConnected = YES; + if (![self.registrar tryToLoadValidCheckinInfo]) { + // Checkin info is not available. This may be due to the checkin still being fetched. + if (self.connectHandler) { + NSError *error = [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeMissingDeviceID]; + self.connectHandler(error); + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient009, + @"Failed to connect to MCS. No deviceID and secret found."); + // Return for now. If checkin is, in fact, retrieved, the + // |kFIRMessagingCheckinFetchedNotification| will be fired. + return; + } + [self setupConnectionAndConnect]; +} + +- (void)disconnect { + // user called disconnect + // We don't want to connect later even if no network is available. + [self disconnectWithTryToConnectLater:NO]; +} + +/** + * Disconnect the current client connection. Also explicitly stop and connction retries. + * + * @param tryToConnectLater If YES will try to connect later when sending upstream messages + * else if NO do not connect again until user explicitly calls + * connect. + */ +- (void)disconnectWithTryToConnectLater:(BOOL)tryToConnectLater { + + self.stayConnected = tryToConnectLater; + [self.connection signOut]; + _FIRMessagingDevAssert(self.connection.state == kFIRMessagingConnectionNotConnected, + @"FIRMessaging connection did not disconnect"); + + // since we can disconnect while still trying to establish the connection it's required to + // cancel all performSelectors else the object might be retained + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(tryToConnect) + object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(didConnectTimeout) + object:nil]; + self.connectHandler = nil; +} + +#pragma mark - Checkin Notification +- (void)checkinFetched:(NSNotification *)notification { + // A failed checkin may have been the reason for the connection failure. Attempt a connection + // if the checkin fetched notification is fired. + if (self.stayConnected && !self.isConnected) { + [self connect]; + } +} + +#pragma mark - Messages + +- (void)sendMessage:(GPBMessage *)message { + [self.connection sendProto:message]; +} + +- (void)sendOnConnectOrDrop:(GPBMessage *)message { + [self.connection sendOnConnectOrDrop:message]; +} + +#pragma mark - FIRMessagingConnectionDelegate + +- (void)connection:(FIRMessagingConnection *)fcmConnection + didCloseForReason:(FIRMessagingConnectionCloseReason)reason { + + self.lastDisconnectedTimestamp = FIRMessagingCurrentTimestampInMilliseconds(); + + if (reason == kFIRMessagingConnectionCloseReasonSocketDisconnected) { + // Cancel the not-yet-triggered timeout task before rescheduling, in case the previous sign in + // failed, due to a connection error caused by bad network. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(didConnectTimeout) + object:nil]; + } + if (self.stayConnected) { + [self scheduleConnectRetry]; + } +} + +- (void)didLoginWithConnection:(FIRMessagingConnection *)fcmConnection { + // Cancel the not-yet-triggered timeout task. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(didConnectTimeout) + object:nil]; + self.connectRetryCount = 0; + self.lastConnectedTimestamp = FIRMessagingCurrentTimestampInMilliseconds(); + + + [self.dataMessageManager setDeviceAuthID:self.registrar.deviceAuthID + secretToken:self.registrar.secretToken]; + if (self.connectHandler) { + self.connectHandler(nil); + // notified the third party app with the registrationId. + // we don't want them to know about the connection status and how it changes + // so remove this handler + self.connectHandler = nil; + } +} + +- (void)connectionDidRecieveMessage:(GtalkDataMessageStanza *)message { + NSDictionary *parsedMessage = [self.dataMessageManager processPacket:message]; + if ([parsedMessage count]) { + [self.dataMessageManager didReceiveParsedMessage:parsedMessage]; + } +} + +- (int)connectionDidReceiveAckForRmqIds:(NSArray *)rmqIds { + NSSet *rmqIDSet = [NSSet setWithArray:rmqIds]; + NSMutableArray *messagesSent = [NSMutableArray arrayWithCapacity:rmqIds.count]; + [self.rmq2Manager scanWithRmqMessageHandler:nil + dataMessageHandler:^(int64_t rmqId, GtalkDataMessageStanza *stanza) { + NSString *rmqIdString = [NSString stringWithFormat:@"%lld", rmqId]; + if ([rmqIDSet containsObject:rmqIdString]) { + [messagesSent addObject:stanza]; + } + }]; + for (GtalkDataMessageStanza *message in messagesSent) { + [self.dataMessageManager didSendDataMessageStanza:message]; + } + return [self.rmq2Manager removeRmqMessagesWithRmqIds:rmqIds]; +} + +#pragma mark - Private + +- (void)setupConnectionAndConnect { + [self setupConnection]; + [self tryToConnect]; +} + +- (void)setupConnection { + NSString *host = FIRMessagingServerHost(); + NSUInteger port = FIRMessagingServerPort(); + _FIRMessagingDevAssert([host length] > 0 && port != 0, @"Invalid port or host"); + + if (self.connection != nil) { + // if there is an old connection, explicitly sign it off. + [self.connection signOut]; + self.connection.delegate = nil; + } + self.connection = [[FIRMessagingConnection alloc] initWithAuthID:self.registrar.deviceAuthID + token:self.registrar.secretToken + host:host + port:port + runLoop:[NSRunLoop mainRunLoop] + rmq2Manager:self.rmq2Manager + fcmManager:self.dataMessageManager]; + self.connection.delegate = self; +} + +- (void)tryToConnect { + if (!self.stayConnected) { + return; + } + + // Cancel any other pending signin requests. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(tryToConnect) + object:nil]; + + // Do not re-sign in if there is already a connection in progress. + if (self.connection.state != kFIRMessagingConnectionNotConnected) { + return; + } + + _FIRMessagingDevAssert(self.registrar.deviceAuthID.length > 0 && + self.registrar.secretToken.length > 0 && + self.connection != nil, + @"Invalid state cannot connect"); + + self.connectRetryCount = MIN(kMaxRetryExponent, self.connectRetryCount + 1); + [self performSelector:@selector(didConnectTimeout) + withObject:nil + afterDelay:self.connectionTimeoutInterval]; + [self.connection signIn]; +} + +- (void)didConnectTimeout { + _FIRMessagingDevAssert(self.connection.state != kFIRMessagingConnectionSignedIn, + @"Invalid state for MCS connection"); + + if (self.stayConnected) { + [self.connection signOut]; + [self scheduleConnectRetry]; + } +} + +#pragma mark - Schedulers + +- (void)scheduleConnectRetry { + GULReachabilityStatus status = self.reachability.reachabilityStatus; + BOOL isReachable = (status == kGULReachabilityViaWifi || status == kGULReachabilityViaCellular); + if (!isReachable) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient010, + @"Internet not reachable when signing into MCS during a retry"); + + FIRMessagingConnectCompletionHandler handler = [self.connectHandler copy]; + // disconnect before issuing a callback + [self disconnectWithTryToConnectLater:YES]; + NSError *error = + [NSError errorWithDomain:@"No internet available, cannot connect to FIRMessaging" + code:kFIRMessagingErrorCodeNetwork + userInfo:nil]; + if (handler) { + handler(error); + self.connectHandler = nil; + } + return; + } + + NSUInteger retryInterval = [self nextRetryInterval]; + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient011, + @"Failed to sign in to MCS, retry in %lu seconds", + _FIRMessaging_UL(retryInterval)); + [self performSelector:@selector(tryToConnect) withObject:nil afterDelay:retryInterval]; +} + +- (NSUInteger)nextRetryInterval { + return 1u << self.connectRetryCount; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.h new file mode 100644 index 0000000..8f22290 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRMessagingCodedInputStream : NSObject + +@property(nonatomic, readonly, assign) size_t offset; + +- (instancetype)initWithData:(NSData *)data; +- (BOOL)readTag:(int8_t *)tag; +- (BOOL)readLength:(int32_t *)length; +- (NSData *)readDataWithLength:(uint32_t)length; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.m new file mode 100644 index 0000000..82c0677 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingCodedInputStream.m @@ -0,0 +1,142 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingCodedInputStream.h" +#import "FIRMessagingDefines.h" + +typedef struct { + const void *bytes; + size_t bufferSize; + size_t bufferPos; +} BufferState; + +static BOOL CheckSize(BufferState *state, size_t size) { + size_t newSize = state->bufferPos + size; + if (newSize > state->bufferSize) { + return NO; + } + return YES; +} + +static BOOL ReadRawByte(BufferState *state, int8_t *output) { + _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters"); + + if (CheckSize(state, sizeof(int8_t))) { + *output = ((int8_t *)state->bytes)[state->bufferPos++]; + return YES; + } + return NO; +} + +static BOOL ReadRawVarInt32(BufferState *state, int32_t *output) { + _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters"); + + int8_t tmp = 0; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + *output = tmp; + return YES; + } + int32_t result = tmp & 0x7f; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + if (!ReadRawByte(state, &tmp)) { + return NO; + } + result |= tmp << 28; + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; ++i) { + if (!ReadRawByte(state, &tmp)) { + return NO; + } + if (tmp >= 0) { + *output = result; + return YES; + } + } + return NO; + } + } + } + } + *output = result; + return YES; +} + +@interface FIRMessagingCodedInputStream() + +@property(nonatomic, readwrite, strong) NSData *buffer; +@property(nonatomic, readwrite, assign) BufferState state; + +@end + +@implementation FIRMessagingCodedInputStream; + +- (instancetype)initWithData:(NSData *)data { + self = [super init]; + if (self) { + _buffer = data; + _state.bytes = _buffer.bytes; + _state.bufferSize = _buffer.length; + } + return self; +} + +- (size_t)offset { + return _state.bufferPos; +} + +- (BOOL)readTag:(int8_t *)tag { + return ReadRawByte(&_state, tag); +} + +- (BOOL)readLength:(int32_t *)length { + return ReadRawVarInt32(&_state, length); +} + +- (NSData *)readDataWithLength:(uint32_t)length { + if (!CheckSize(&_state, length)) { + return nil; + } + const void *bytesToRead = _state.bytes + _state.bufferPos; + NSData *result = [NSData dataWithBytes:bytesToRead length:length]; + _state.bufferPos += length; + return result; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.h new file mode 100644 index 0000000..25a018c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.h @@ -0,0 +1,106 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRMessagingConnection; +@class FIRMessagingDataMessageManager; +@class FIRMessagingRmqManager; + +@class GtalkDataMessageStanza; +@class GPBMessage; + +typedef void (^FIRMessagingMessageHandler)(NSDictionary *); + +typedef NS_ENUM(NSUInteger, FIRMessagingConnectionState) { + kFIRMessagingConnectionNotConnected = 0, + kFIRMessagingConnectionConnecting, + kFIRMessagingConnectionConnected, + kFIRMessagingConnectionSignedIn, +}; + +typedef NS_ENUM(NSUInteger, FIRMessagingConnectionCloseReason) { + kFIRMessagingConnectionCloseReasonSocketDisconnected = 0, + kFIRMessagingConnectionCloseReasonTimeout, + kFIRMessagingConnectionCloseReasonUserDisconnect, +}; + +@protocol FIRMessagingConnectionDelegate + +- (void)connection:(FIRMessagingConnection *)fcmConnection + didCloseForReason:(FIRMessagingConnectionCloseReason)reason; +- (void)didLoginWithConnection:(FIRMessagingConnection *)fcmConnection; +- (void)connectionDidRecieveMessage:(GtalkDataMessageStanza *)message; +/** + * Called when a stream ACK or a selective ACK are received - this indicates the + * message has been received by MCS. + * @return The count of rmqIds deleted from the client RMQ store. + */ +- (int)connectionDidReceiveAckForRmqIds:(NSArray *)rmqIds; + +@end + + +/** + * This class maintains the actual FIRMessaging connection that we use to receive and send messages + * while the app is in foreground. Once we have a registrationID from the FIRMessaging backend we + * are able to set up this connection which is used for any further communication with FIRMessaging + * backend. In case the connection breaks off while the app is still being used we try to rebuild + * the connection with an exponential backoff. + * + * This class also notifies the delegate about the main events happening in the lifcycle of the + * FIRMessaging connection (read FIRMessagingConnectionDelegate). All of the `on-the-wire` + * interactions with FIRMessaging are channelled through here. + */ +@interface FIRMessagingConnection : NSObject + +@property(nonatomic, readonly, assign) FIRMessagingConnectionState state; +@property(nonatomic, readonly, copy) NSString *host; +@property(nonatomic, readonly, assign) NSUInteger port; +@property(nonatomic, readwrite, weak) id delegate; + +- (instancetype)initWithAuthID:(NSString *)authId + token:(NSString *)token + host:(NSString *)host + port:(NSUInteger)port + runLoop:(NSRunLoop *)runLoop + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + fcmManager:(FIRMessagingDataMessageManager *)dataMessageManager; + +- (void)signIn; // connect +- (void)signOut; // disconnect + +/** + * Teardown the FIRMessaging connection and deallocate the resources being held up by the + * connection. + */ +- (void)teardown; + +/** + * Send proto to the wire. The message will be cached before we try to send so that in case of + * failure we can send it again later on when we have connection. + */ +- (void)sendProto:(GPBMessage *)proto; + +/** + * Send a message after the currently in progress connection succeeds, otherwise drop it. + * + * This should be used for TTL=0 messages that force a reconnect. They shouldn't be persisted + * in the RMQ, but they should be sent if the reconnect is successful. + */ +- (void)sendOnConnectOrDrop:(GPBMessage *)message; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.m new file mode 100644 index 0000000..8694326 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConnection.m @@ -0,0 +1,708 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingConnection.h" + +#import "Protos/GtalkCore.pbobjc.h" +#import "Protos/GtalkExtensions.pbobjc.h" + +#import "FIRMessaging.h" +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingSecureSocket.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessagingVersionUtilities.h" +#import "FIRMessaging_Private.h" + +static NSInteger const kIqSelectiveAck = 12; +static NSInteger const kIqStreamAck = 13; +static int const kInvalidStreamId = -1; +// Threshold for number of messages removed that we will ack, for short lived connections +static int const kMessageRemoveAckThresholdCount = 5; + +static NSTimeInterval const kHeartbeatInterval = 30.0; +static NSTimeInterval const kConnectionTimeout = 20.0; +static int32_t const kAckingInterval = 10; + +static NSString *const kUnackedS2dIdKey = @"FIRMessagingUnackedS2dIdKey"; +static NSString *const kAckedS2dIdMapKey = @"FIRMessagingAckedS2dIdMapKey"; + +static NSString *const kRemoteFromAddress = @"from"; + +@interface FIRMessagingD2SInfo : NSObject + +@property(nonatomic, readwrite, assign) int streamId; +@property(nonatomic, readwrite, strong) NSString *d2sID; +- (instancetype)initWithStreamId:(int)streamId d2sId:(NSString *)d2sID; + +@end + +@implementation FIRMessagingD2SInfo + +- (instancetype)initWithStreamId:(int)streamId d2sId:(NSString *)d2sID { + self = [super init]; + if (self) { + _streamId = streamId; + _d2sID = [d2sID copy]; + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([object isKindOfClass:[self class]]) { + FIRMessagingD2SInfo *other = (FIRMessagingD2SInfo *)object; + return self.streamId == other.streamId && [self.d2sID isEqualToString:other.d2sID]; + } + return NO; +} + +- (NSUInteger)hash { + return [self.d2sID hash]; +} + +@end + +@interface FIRMessagingConnection () + +@property(nonatomic, readwrite, weak) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, weak) FIRMessagingDataMessageManager *dataMessageManager; + +@property(nonatomic, readwrite, assign) FIRMessagingConnectionState state; +@property(nonatomic, readwrite, copy) NSString *host; +@property(nonatomic, readwrite, assign) NSUInteger port; + +@property(nonatomic, readwrite, strong) NSString *authId; +@property(nonatomic, readwrite, strong) NSString *token; + +@property(nonatomic, readwrite, strong) FIRMessagingSecureSocket *socket; + +@property(nonatomic, readwrite, assign) int64_t lastLoginServerTimestamp; +@property(nonatomic, readwrite, assign) int lastStreamIdAcked; +@property(nonatomic, readwrite, assign) int inStreamId; +@property(nonatomic, readwrite, assign) int outStreamId; + +@property(nonatomic, readwrite, strong) NSMutableArray *unackedS2dIds; +@property(nonatomic, readwrite, strong) NSMutableDictionary *ackedS2dMap; +@property(nonatomic, readwrite, strong) NSMutableArray *d2sInfos; +// ttl=0 messages that need to be sent as soon as we establish a connection +@property(nonatomic, readwrite, strong) NSMutableArray *sendOnConnectMessages; + +@property(nonatomic, readwrite, strong) NSRunLoop *runLoop; + +@end + + +@implementation FIRMessagingConnection; + +- (instancetype)initWithAuthID:(NSString *)authId + token:(NSString *)token + host:(NSString *)host + port:(NSUInteger)port + runLoop:(NSRunLoop *)runLoop + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + fcmManager:(FIRMessagingDataMessageManager *)dataMessageManager { + self = [super init]; + if (self) { + _authId = [authId copy]; + _token = [token copy]; + _host = [host copy]; + _port = port; + _runLoop = runLoop; + _rmq2Manager = rmq2Manager; + _dataMessageManager = dataMessageManager; + + _d2sInfos = [NSMutableArray array]; + + _unackedS2dIds = [NSMutableArray arrayWithArray:[_rmq2Manager unackedS2dRmqIds]]; + _ackedS2dMap = [NSMutableDictionary dictionary]; + _sendOnConnectMessages = [NSMutableArray array]; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"host: %@, port: %lu, stream id in: %d, stream id out: %d", + self.host, + _FIRMessaging_UL(self.port), + self.inStreamId, + self.outStreamId]; +} + +- (void)signIn { + _FIRMessagingDevAssert(self.state == kFIRMessagingConnectionNotConnected, @"Invalid connection state."); + if (self.state != kFIRMessagingConnectionNotConnected) { + return; + } + + // break it up for testing + [self setupConnectionSocket]; + [self connectToSocket:self.socket]; +} + +- (void)setupConnectionSocket { + self.socket = [[FIRMessagingSecureSocket alloc] init]; + self.socket.delegate = self; +} + +- (void)connectToSocket:(FIRMessagingSecureSocket *)socket { + self.state = kFIRMessagingConnectionConnecting; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection000, + @"Start connecting to FIRMessaging service."); + [socket connectToHost:self.host port:self.port onRunLoop:self.runLoop]; +} + +- (void)signOut { + // Clear the list of messages to be sent on connect. This will only + // have messages in it if an error happened before receiving the LoginResponse. + [self.sendOnConnectMessages removeAllObjects]; + + if (self.state == kFIRMessagingConnectionSignedIn) { + [self sendClose]; + } + if (self.state != kFIRMessagingConnectionNotConnected) { + [self disconnect]; + } +} + +- (void)teardown { + if (self.state != kFIRMessagingConnectionNotConnected) { + [self disconnect]; + } +} + +#pragma mark - FIRMessagingSecureSocketDelegate + +- (void)secureSocketDidConnect:(FIRMessagingSecureSocket *)socket { + self.state = kFIRMessagingConnectionConnected; + self.lastStreamIdAcked = 0; + self.inStreamId = 0; + self.outStreamId = 0; + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection001, + @"Connected to FIRMessaging service."); + [self resetUnconfirmedAcks]; + [self sendLoginRequest:self.authId token:self.token]; +} + +- (void)didDisconnectWithSecureSocket:(FIRMessagingSecureSocket *)socket { + _FIRMessagingDevAssert(self.socket == socket, @"Invalid socket"); + _FIRMessagingDevAssert(self.socket.state == kFIRMessagingSecureSocketClosed, @"Socket already closed"); + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection002, + @"Secure socket disconnected from FIRMessaging service."); + [self disconnect]; + [self.delegate connection:self didCloseForReason:kFIRMessagingConnectionCloseReasonSocketDisconnected]; +} + +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didReceiveData:(NSData *)data + withTag:(int8_t)tag { + if (tag < 0) { + // Invalid proto tag + return; + } + + Class klassForTag = FIRMessagingGetClassForTag((FIRMessagingProtoTag)tag); + if ([klassForTag isSubclassOfClass:[NSNull class]]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeConnection003, @"Invalid tag %d for proto", + tag); + return; + } + + GPBMessage *proto = [klassForTag parseFromData:data error:NULL]; + if (tag == kFIRMessagingProtoTagLoginResponse && self.state != kFIRMessagingConnectionConnected) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection004, + @"Should not receive generated message when the connection is not connected."); + return; + } else if (tag != kFIRMessagingProtoTagLoginResponse && self.state != kFIRMessagingConnectionSignedIn) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection005, + @"Should not receive generated message when the connection is not signed in."); + return; + } + + // If traffic is received after a heartbeat it is safe to assume the connection is healthy. + [self cancelConnectionTimeoutTask]; + [self performSelector:@selector(sendHeartbeatPing) + withObject:nil + afterDelay:kHeartbeatInterval]; + + [self willProcessProto:proto]; + switch (tag) { + case kFIRMessagingProtoTagLoginResponse: + [self didReceiveLoginResponse:(GtalkLoginResponse *)proto]; + break; + case kFIRMessagingProtoTagDataMessageStanza: + [self didReceiveDataMessageStanza:(GtalkDataMessageStanza *)proto]; + break; + case kFIRMessagingProtoTagHeartbeatPing: + [self didReceiveHeartbeatPing:(GtalkHeartbeatPing *)proto]; + break; + case kFIRMessagingProtoTagHeartbeatAck: + [self didReceiveHeartbeatAck:(GtalkHeartbeatAck *)proto]; + break; + case kFIRMessagingProtoTagClose: + [self didReceiveClose:(GtalkClose *)proto]; + break; + case kFIRMessagingProtoTagIqStanza: + [self handleIqStanza:(GtalkIqStanza *)proto]; + break; + default: + [self didReceiveUnhandledProto:proto]; + break; + } +} + +// Called from secure socket once we have send the proto with given rmqId over the wire +// since we are mostly concerned with user facing messages which certainly have a rmqId +// we can retrieve them from the Rmq if necessary to look at stuff but for now we just +// log it. +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didSendProtoWithTag:(int8_t)tag + rmqId:(NSString *)rmqId { + // log the message + [self logMessage:rmqId messageType:tag isOut:YES]; +} + +#pragma mark - FIRMessagingTestConnection + +- (void)sendProto:(GPBMessage *)proto { + FIRMessagingProtoTag tag = FIRMessagingGetTagForProto(proto); + if (tag == kFIRMessagingProtoTagLoginRequest && self.state != kFIRMessagingConnectionConnected) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection006, + @"Cannot send generated message when the connection is not connected."); + return; + } else if (tag != kFIRMessagingProtoTagLoginRequest && self.state != kFIRMessagingConnectionSignedIn) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection007, + @"Cannot send generated message when the connection is not signed in."); + return; + } + + _FIRMessagingDevAssert(self.socket != nil, @"Socket shouldn't be nil"); + if (self.socket == nil) { + return; + } + + [self willSendProto:proto]; + + [self.socket sendData:proto.data withTag:tag rmqId:FIRMessagingGetRmq2Id(proto)]; +} + +- (void)sendOnConnectOrDrop:(GPBMessage *)message { + if (self.state == kFIRMessagingConnectionSignedIn) { + // If a connection has already been established, send normally + [self sendProto:message]; + } else { + // Otherwise add them to the list of messages to send after login + [self.sendOnConnectMessages addObject:message]; + } +} + ++ (GtalkLoginRequest *)loginRequestWithToken:(NSString *)token authID:(NSString *)authID { + GtalkLoginRequest *login = [[GtalkLoginRequest alloc] init]; + login.accountId = 1000000; + login.authService = GtalkLoginRequest_AuthService_AndroidId; + login.authToken = token; + login.id_p = [NSString stringWithFormat:@"%@-%@", @"ios", FIRMessagingCurrentLibraryVersion()]; + login.domain = @"mcs.android.com"; + login.deviceId = [NSString stringWithFormat:@"android-%llx", authID.longLongValue]; + login.networkType = [self currentNetworkType]; + login.resource = authID; + login.user = authID; + login.useRmq2 = YES; + login.lastRmqId = 1; // Sending not enabled yet so this stays as 1. + return login; +} + ++ (int32_t)currentNetworkType { + // http://developer.android.com/reference/android/net/ConnectivityManager.html + int32_t fcmNetworkType; + FIRMessagingNetworkStatus type = [[FIRMessaging messaging] networkType]; + switch (type) { + case kFIRMessagingReachabilityReachableViaWiFi: + fcmNetworkType = 1; + break; + + case kFIRMessagingReachabilityReachableViaWWAN: + fcmNetworkType = 0; + break; + + default: + fcmNetworkType = -1; + break; + } + return fcmNetworkType; +} + +- (void)sendLoginRequest:(NSString *)authId + token:(NSString *)token { + GtalkLoginRequest *login = [[self class] loginRequestWithToken:token authID:authId]; + + // clear the messages sent during last connection + if ([self.d2sInfos count]) { + [self.d2sInfos removeAllObjects]; + } + + if (self.unackedS2dIds.count > 0) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection008, + @"There are unacked persistent Ids in the login request: %@", + [self.unackedS2dIds.description stringByReplacingOccurrencesOfString:@"%" + withString:@"%%"]); + } + // Send out acks. + for (NSString *unackedPersistentS2dId in self.unackedS2dIds) { + [login.receivedPersistentIdArray addObject:unackedPersistentS2dId]; + } + + GtalkSetting *setting = [[GtalkSetting alloc] init]; + setting.name = @"new_vc"; + setting.value = @"1"; + [login.settingArray addObject:setting]; + + [self sendProto:login]; +} + +- (void)sendHeartbeatAck { + [self sendProto:[[GtalkHeartbeatAck alloc] init]]; +} + +- (void)sendHeartbeatPing { + // cancel the previous heartbeat request. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(sendHeartbeatPing) + object:nil]; + [self scheduleConnectionTimeoutTask]; + [self sendProto:[[GtalkHeartbeatPing alloc] init]]; +} + ++ (GtalkIqStanza *)createStreamAck { + GtalkIqStanza *iq = [[GtalkIqStanza alloc] init]; + iq.type = GtalkIqStanza_IqType_Set; + iq.id_p = @""; + GtalkExtension *ext = [[GtalkExtension alloc] init]; + ext.id_p = kIqStreamAck; + ext.data_p = @""; + iq.extension = ext; + return iq; +} + +- (void)sendStreamAck { + GtalkIqStanza *iq = [[self class] createStreamAck]; + [self sendProto:iq]; +} + +- (void)sendClose { + [self sendProto:[[GtalkClose alloc] init]]; +} + +- (void)handleIqStanza:(GtalkIqStanza *)iq { + if (iq.hasExtension) { + if (iq.extension.id_p == kIqStreamAck) { + [self didReceiveStreamAck:iq]; + return; + } + if (iq.extension.id_p == kIqSelectiveAck) { + [self didReceiveSelectiveAck:iq]; + return; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection009, @"Unknown ack extension id %d.", + iq.extension.id_p); + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection010, @"Ip stanza without extension."); + } + [self didReceiveUnhandledProto:iq]; +} + +- (void)didReceiveLoginResponse:(GtalkLoginResponse *)loginResponse { + if (loginResponse.hasError) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection011, + @"Login error with type: %@, message: %@.", loginResponse.error.type, + loginResponse.error.message); + return; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection012, @"Logged onto MCS service."); + // We sent the persisted list of unack'd messages with login so we can assume they have been ack'd + // by the server. + _FIRMessagingDevAssert(self.unackedS2dIds.count == 0, @"No ids present"); + _FIRMessagingDevAssert(self.outStreamId == 1, @"Login should be the first stream id"); + + self.state = kFIRMessagingConnectionSignedIn; + self.lastLoginServerTimestamp = loginResponse.serverTimestamp; + [self.delegate didLoginWithConnection:self]; + [self sendHeartbeatPing]; + + // Add all the TTL=0 messages on connect + for (GPBMessage *message in self.sendOnConnectMessages) { + [self sendProto:message]; + } + [self.sendOnConnectMessages removeAllObjects]; +} + +- (void)didReceiveHeartbeatPing:(GtalkHeartbeatPing *)heartbeatPing { + [self sendHeartbeatAck]; +} + +- (void)didReceiveHeartbeatAck:(GtalkHeartbeatAck *)heartbeatAck { +} + +- (void)didReceiveDataMessageStanza:(GtalkDataMessageStanza *)dataMessageStanza { + // TODO: Maybe add support raw data later + [self.delegate connectionDidRecieveMessage:dataMessageStanza]; +} + +- (void)didReceiveUnhandledProto:(GPBMessage *)proto { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection013, @"Received unhandled proto"); +} + +- (void)didReceiveStreamAck:(GtalkIqStanza *)iq { + // Server received some stuff from us we don't really need to do anything special +} + +- (void)didReceiveSelectiveAck:(GtalkIqStanza *)iq { + GtalkExtension *extension = iq.extension; + if (extension) { + int extensionId = extension.id_p; + if (extensionId == kIqSelectiveAck) { + + NSString *dataString = extension.data_p; + GtalkSelectiveAck *selectiveAck = [[GtalkSelectiveAck alloc] init]; + [selectiveAck mergeFromData:[dataString dataUsingEncoding:NSUTF8StringEncoding] + extensionRegistry:nil]; + + NSArray *acks = [selectiveAck idArray]; + + // we've received ACK's + [self.delegate connectionDidReceiveAckForRmqIds:acks]; + + // resend unacked messages + [self.dataMessageManager resendMessagesWithConnection:self]; + } + } +} + +- (void)didReceiveClose:(GtalkClose *)close { + [self disconnect]; +} + +- (void)willProcessProto:(GPBMessage *)proto { + self.inStreamId++; + + if ([proto isKindOfClass:GtalkDataMessageStanza.class]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection014, + @"RMQ: Receiving %@ with rmq_id: %@ incoming stream Id: %d", + proto.class, FIRMessagingGetRmq2Id(proto), self.inStreamId); + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection015, + @"RMQ: Receiving %@ with incoming stream Id: %d.", proto.class, + self.inStreamId); + } + int streamId = FIRMessagingGetLastStreamId(proto); + if (streamId != kInvalidStreamId) { + // confirm the D2S messages that were sent by us + [self confirmAckedD2sIdsWithStreamId:streamId]; + + // We can now confirm that our ack was received by the server and start our unack'd list fresh + // with the proto we just received. + [self confirmAckedS2dIdsWithStreamId:streamId]; + } + NSString *rmq2Id = FIRMessagingGetRmq2Id(proto); + if (rmq2Id != nil) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection016, + @"RMQ: Add unacked persistent Id: %@.", + [rmq2Id stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]); + [self.unackedS2dIds addObject:rmq2Id]; + [self.rmq2Manager saveS2dMessageWithRmqId:rmq2Id]; // RMQ save + } + BOOL explicitAck = ([proto isKindOfClass:[GtalkDataMessageStanza class]] && + [(GtalkDataMessageStanza *)proto immediateAck]); + // If we have not sent anything and the ack threshold has been reached then explicitly send one + // to notify the server that we have received messages. + if (self.inStreamId - self.lastStreamIdAcked >= kAckingInterval || explicitAck) { + [self sendStreamAck]; + } +} + +- (void)willSendProto:(GPBMessage *)proto { + self.outStreamId++; + + NSString *rmq2Id = FIRMessagingGetRmq2Id(proto); + if ([rmq2Id length]) { + FIRMessagingD2SInfo *d2sInfo = [[FIRMessagingD2SInfo alloc] initWithStreamId:self.outStreamId d2sId:rmq2Id]; + [self.d2sInfos addObject:d2sInfo]; + } + + // each time we send a d2s message, it acks previously received + // s2d messages via the last (s2d) stream id received. + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection017, + @"RMQ: Sending %@ with outgoing stream Id: %d.", proto.class, + self.outStreamId); + // We have received messages since last time we sent something - send ack info to server. + if (self.inStreamId > self.lastStreamIdAcked) { + FIRMessagingSetLastStreamId(proto, self.inStreamId); + self.lastStreamIdAcked = self.inStreamId; + } + + if (self.unackedS2dIds.count > 0) { + // Move all 'unack'd' messages to the ack'd map so they can be removed once the + // ack is confirmed. + NSArray *ackedS2dIds = [NSArray arrayWithArray:self.unackedS2dIds]; + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection018, @"RMQ: Mark persistent Ids as acked: %@.", + [ackedS2dIds.description stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]); + [self.unackedS2dIds removeAllObjects]; + self.ackedS2dMap[[@(self.outStreamId) stringValue]] = ackedS2dIds; + } +} + +#pragma mark - Private + +/** + * This processes the s2d message received in reference to the d2s messages + * that we have sent before. + */ +- (void)confirmAckedD2sIdsWithStreamId:(int)lastReceivedStreamId { + NSMutableArray *d2sIdsAcked = [NSMutableArray array]; + for (FIRMessagingD2SInfo *d2sInfo in self.d2sInfos) { + if (lastReceivedStreamId < d2sInfo.streamId) { + break; + } + [d2sIdsAcked addObject:d2sInfo]; + } + + NSMutableArray *rmqIds = [NSMutableArray arrayWithCapacity:[d2sIdsAcked count]]; + // remove ACK'ed messages + for (FIRMessagingD2SInfo *d2sInfo in d2sIdsAcked) { + if ([d2sInfo.d2sID length]) { + [rmqIds addObject:d2sInfo.d2sID]; + } + [self.d2sInfos removeObject:d2sInfo]; + } + [self.delegate connectionDidReceiveAckForRmqIds:rmqIds]; + int count = [self.delegate connectionDidReceiveAckForRmqIds:rmqIds]; + if (kMessageRemoveAckThresholdCount > 0 && count >= kMessageRemoveAckThresholdCount) { + // For short lived connections, if a large number of messages are removed, send an + // ack straight away so the server knows that this message was received. + [self sendStreamAck]; + } +} + +/** + * Called when a stream ACK or a selective ACK are received - this indicates the message has + * been received by MCS. + */ +- (void)didReceiveAckForRmqIds:(NSArray *)rmqIds { + // TODO: let the user know that the following messages were received by the server +} + +- (void)confirmAckedS2dIdsWithStreamId:(int)lastReceivedStreamId { + // If the server hasn't received the streamId yet. + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection019, + @"RMQ: Server last received stream Id: %d.", lastReceivedStreamId); + if (lastReceivedStreamId < self.outStreamId) { + // TODO: This could be a good indicator that we need to re-send something (acks)? + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection020, + @"RMQ: There are unsent messages that should be send...\n" + "server received: %d\nlast stream id sent: %d", + lastReceivedStreamId, self.outStreamId); + } + + NSSet *ackedStreamIds = + [self.ackedS2dMap keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) { + NSString *streamId = key; + return streamId.intValue <= lastReceivedStreamId; + }]; + NSMutableArray *s2dIdsToDelete = [NSMutableArray array]; + + for (NSString *streamId in ackedStreamIds) { + NSArray *ackedS2dIds = self.ackedS2dMap[streamId]; + if (ackedS2dIds.count > 0) { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeConnection021, + @"RMQ: Mark persistent Ids as confirmed by stream id %@: %@.", streamId, + [ackedS2dIds.description stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]); + [self.ackedS2dMap removeObjectForKey:streamId]; + } + + [s2dIdsToDelete addObjectsFromArray:ackedS2dIds]; + } + + // clean up s2d ids that the server knows we've received. + // we let the server know via a s2d last stream id received in a + // d2s message. the server lets us know it has received our d2s + // message via a d2s last stream id received in a s2d message. + [self.rmq2Manager removeS2dIds:s2dIdsToDelete]; +} + +- (void)resetUnconfirmedAcks { + [self.ackedS2dMap enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [self.unackedS2dIds addObjectsFromArray:obj]; + }]; + [self.ackedS2dMap removeAllObjects]; +} + +- (void)disconnect { + _FIRMessagingDevAssert(self.state != kFIRMessagingConnectionNotConnected, @"Connection already not connected"); + // cancel pending timeout tasks. + [self cancelConnectionTimeoutTask]; + // cancel pending heartbeat. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(sendHeartbeatPing) + object:nil]; + // Unset the delegate. FIRMessagingConnection will not receive further events from the socket from now on. + self.socket.delegate = nil; + [self.socket disconnect]; + self.state = kFIRMessagingConnectionNotConnected; +} + +- (void)connectionTimedOut { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection022, + @"Connection to FIRMessaging service timed out."); + [self disconnect]; + [self.delegate connection:self didCloseForReason:kFIRMessagingConnectionCloseReasonTimeout]; +} + +- (void)scheduleConnectionTimeoutTask { + // cancel the previous heartbeat timeout event and schedule a new one. + [self cancelConnectionTimeoutTask]; + [self performSelector:@selector(connectionTimedOut) + withObject:nil + afterDelay:[self connectionTimeoutInterval]]; +} + +- (void)cancelConnectionTimeoutTask { + // cancel pending timeout tasks. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(connectionTimedOut) + object:nil]; +} + +- (void)logMessage:(NSString *)description messageType:(int)messageType isOut:(BOOL)isOut { + messageType = isOut ? -messageType : messageType; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection023, + @"Send msg: %@ type: %d inStreamId: %d outStreamId: %d", description, + messageType, self.inStreamId, self.outStreamId); +} + +- (NSTimeInterval)connectionTimeoutInterval { + return kConnectionTimeout; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.h new file mode 100644 index 0000000..9a3ce04 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Global constants to be put here. + * + */ +#import + +#ifndef _FIRMessaging_CONSTANTS_H +#define _FIRMessaging_CONSTANTS_H + +FOUNDATION_EXPORT NSString *const kFIRMessagingRawDataKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingCollapseKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingFromKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingSendTo; +FOUNDATION_EXPORT NSString *const kFIRMessagingSendTTL; +FOUNDATION_EXPORT NSString *const kFIRMessagingSendDelay; +FOUNDATION_EXPORT NSString *const kFIRMessagingSendMessageID; +FOUNDATION_EXPORT NSString *const KFIRMessagingSendMessageAppData; + +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageInternalReservedKeyword; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessagePersistentIDKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageIDKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageAPNSContentAvailableKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageSyncViaMCSKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageSyncMessageTTLKey; +FOUNDATION_EXPORT NSString *const kFIRMessagingMessageLinkKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingRemoteNotificationsProxyEnabledInfoPlistKey; + +FOUNDATION_EXPORT NSString *const kFIRMessagingSubDirectoryName; + +// Notifications +FOUNDATION_EXPORT NSString *const kFIRMessagingCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRMessagingAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRMessagingFCMTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRMessagingInstanceIDTokenRefreshNotification __deprecated_msg("Use kFIRMessagingRegistrationTokenRefreshNotification instead"); +FOUNDATION_EXPORT NSString *const kFIRMessagingRegistrationTokenRefreshNotification; + +FOUNDATION_EXPORT const int kFIRMessagingSendTtlDefault; // 24 hours + +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.m new file mode 100644 index 0000000..e50c923 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingConstants.m @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingConstants.h" + +NSString *const kFIRMessagingRawDataKey = @"rawData"; +NSString *const kFIRMessagingCollapseKey = @"collapse_key"; +NSString *const kFIRMessagingFromKey = @"from"; + +NSString *const kFIRMessagingSendTo = @"google." @"to"; +NSString *const kFIRMessagingSendTTL = @"google." @"ttl"; +NSString *const kFIRMessagingSendDelay = @"google." @"delay"; +NSString *const kFIRMessagingSendMessageID = @"google." @"msg_id"; +NSString *const KFIRMessagingSendMessageAppData = @"google." @"data"; + +NSString *const kFIRMessagingMessageInternalReservedKeyword = @"gcm."; +NSString *const kFIRMessagingMessagePersistentIDKey = @"persistent_id"; + +NSString *const kFIRMessagingMessageIDKey = @"gcm." @"message_id"; +NSString *const kFIRMessagingMessageAPNSContentAvailableKey = @"content-available"; +NSString *const kFIRMessagingMessageSyncViaMCSKey = @"gcm." @"duplex"; +NSString *const kFIRMessagingMessageSyncMessageTTLKey = @"gcm." @"ttl"; +NSString *const kFIRMessagingMessageLinkKey = @"gcm." @"app_link"; + +NSString *const kFIRMessagingRemoteNotificationsProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +NSString *const kFIRMessagingSubDirectoryName = @"Google/FirebaseMessaging"; + +// Notifications +NSString *const kFIRMessagingCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRMessagingAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRMessagingFCMTokenNotification = @"com.firebase.iid.notif.fcm-token"; +NSString *const kFIRMessagingInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +NSString *const kFIRMessagingRegistrationTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; + +const int kFIRMessagingSendTtlDefault = 24 * 60 * 60; // 24 hours diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.h new file mode 100644 index 0000000..83e6444 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerCategory; +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerLocalTimeStart; +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerLocalTimeEnd; +FOUNDATION_EXPORT NSString *const kFIRMessagingContextManagerBodyKey; + +@interface FIRMessagingContextManagerService : NSObject + +/** + * Check if the message is a context manager message or not. + * + * @param message The message to verify. + * + * @return YES if the message is a context manager message else NO. + */ ++ (BOOL)isContextManagerMessage:(NSDictionary *)message; + +/** + * Handle context manager message. + * + * @param message The message to handle. + * + * @return YES if the message was handled successfully else NO. + */ ++ (BOOL)handleContextManagerMessage:(NSDictionary *)message; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.m new file mode 100644 index 0000000..d177014 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingContextManagerService.m @@ -0,0 +1,205 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingContextManagerService.h" + +#import + +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" + +#define kFIRMessagingContextManagerPrefixKey @"google.c.cm." +#define kFIRMessagingContextManagerNotificationKeyPrefix @"gcm.notification." + +static NSString *const kLogTag = @"FIRMessagingAnalytics"; + +static NSString *const kLocalTimeFormatString = @"yyyy-MM-dd HH:mm:ss"; + +static NSString *const kContextManagerPrefixKey = kFIRMessagingContextManagerPrefixKey; + +// Local timed messages (format yyyy-mm-dd HH:mm:ss) +NSString *const kFIRMessagingContextManagerLocalTimeStart = kFIRMessagingContextManagerPrefixKey @"lt_start"; +NSString *const kFIRMessagingContextManagerLocalTimeEnd = kFIRMessagingContextManagerPrefixKey @"lt_end"; + +// Local Notification Params +NSString *const kFIRMessagingContextManagerBodyKey = kFIRMessagingContextManagerNotificationKeyPrefix @"body"; +NSString *const kFIRMessagingContextManagerTitleKey = kFIRMessagingContextManagerNotificationKeyPrefix @"title"; +NSString *const kFIRMessagingContextManagerBadgeKey = kFIRMessagingContextManagerNotificationKeyPrefix @"badge"; +NSString *const kFIRMessagingContextManagerCategoryKey = + kFIRMessagingContextManagerNotificationKeyPrefix @"click_action"; +NSString *const kFIRMessagingContextManagerSoundKey = kFIRMessagingContextManagerNotificationKeyPrefix @"sound"; +NSString *const kFIRMessagingContextManagerContentAvailableKey = + kFIRMessagingContextManagerNotificationKeyPrefix @"content-available"; + +typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) { + FIRMessagingContextManagerMessageTypeNone, + FIRMessagingContextManagerMessageTypeLocalTime, +}; + +@implementation FIRMessagingContextManagerService + ++ (BOOL)isContextManagerMessage:(NSDictionary *)message { + // For now we only support local time in ContextManager. + if (![message[kFIRMessagingContextManagerLocalTimeStart] length]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeContextManagerService000, + @"Received message missing local start time, dropped."); + return NO; + } + + return YES; +} + ++ (BOOL)handleContextManagerMessage:(NSDictionary *)message { + NSString *startTimeString = message[kFIRMessagingContextManagerLocalTimeStart]; + if (startTimeString.length) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeContextManagerService001, + @"%@ Received context manager message with local time %@", kLogTag, + startTimeString); + return [self handleContextManagerLocalTimeMessage:message]; + } + + return NO; +} + ++ (BOOL)handleContextManagerLocalTimeMessage:(NSDictionary *)message { + NSString *startTimeString = message[kFIRMessagingContextManagerLocalTimeStart]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setDateFormat:kLocalTimeFormatString]; + NSDate *startDate = [dateFormatter dateFromString:startTimeString]; + + _FIRMessagingDevAssert(startDate, @"Invalid local start date format %@", startTimeString); + if (!startTimeString) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService002, + @"Invalid local start date format %@. Message dropped", + startTimeString); + return NO; + } + + NSDate *currentDate = [NSDate date]; + + if ([currentDate compare:startDate] == NSOrderedAscending) { + [self scheduleLocalNotificationForMessage:message + atDate:startDate]; + } else { + // check end time has not passed + NSString *endTimeString = message[kFIRMessagingContextManagerLocalTimeEnd]; + if (!endTimeString) { + FIRMessagingLoggerInfo( + kFIRMessagingMessageCodeContextManagerService003, + @"No end date specified for message, start date elapsed. Message dropped."); + return YES; + } + + NSDate *endDate = [dateFormatter dateFromString:endTimeString]; + + _FIRMessagingDevAssert(endDate, @"Invalid local end date format %@", endTimeString); + if (!endTimeString) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService004, + @"Invalid local end date format %@. Message dropped", endTimeString); + return NO; + } + + if ([endDate compare:currentDate] == NSOrderedAscending) { + // end date has already passed drop the message + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeContextManagerService005, + @"End date %@ has already passed. Message dropped.", endTimeString); + return YES; + } + + // schedule message right now (buffer 10s) + [self scheduleLocalNotificationForMessage:message + atDate:[currentDate dateByAddingTimeInterval:10]]; + } + return YES; +} + ++ (void)scheduleLocalNotificationForMessage:(NSDictionary *)message + atDate:(NSDate *)date { +#if TARGET_OS_IOS + NSDictionary *apsDictionary = message; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + UILocalNotification *notification = [[UILocalNotification alloc] init]; +#pragma clang diagnostic pop + + // A great way to understand timezones and UILocalNotifications + // http://stackoverflow.com/questions/18424569/understanding-uilocalnotification-timezone + notification.timeZone = [NSTimeZone defaultTimeZone]; + notification.fireDate = date; + + // In the current solution all of the display stuff goes into a special "aps" dictionary + // being sent in the message. + if ([apsDictionary[kFIRMessagingContextManagerBodyKey] length]) { + notification.alertBody = apsDictionary[kFIRMessagingContextManagerBodyKey]; + } + if ([apsDictionary[kFIRMessagingContextManagerTitleKey] length]) { + // |alertTitle| is iOS 8.2+, so check if we can set it + if ([notification respondsToSelector:@selector(setAlertTitle:)]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + notification.alertTitle = apsDictionary[kFIRMessagingContextManagerTitleKey]; +#pragma pop + } + } + + if (apsDictionary[kFIRMessagingContextManagerSoundKey]) { + notification.soundName = apsDictionary[kFIRMessagingContextManagerSoundKey]; + } + if (apsDictionary[kFIRMessagingContextManagerBadgeKey]) { + notification.applicationIconBadgeNumber = + [apsDictionary[kFIRMessagingContextManagerBadgeKey] integerValue]; + } + if (apsDictionary[kFIRMessagingContextManagerCategoryKey]) { + // |category| is iOS 8.0+, so check if we can set it + if ([notification respondsToSelector:@selector(setCategory:)]) { + notification.category = apsDictionary[kFIRMessagingContextManagerCategoryKey]; + } + } + + NSDictionary *userInfo = [self parseDataFromMessage:message]; + if (userInfo.count) { + notification.userInfo = userInfo; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + UIApplication *application = FIRMessagingUIApplication(); + if (!application) { + return; + } + [application scheduleLocalNotification:notification]; +#pragma clang diagnostic pop +#endif +} + ++ (NSDictionary *)parseDataFromMessage:(NSDictionary *)message { + NSMutableDictionary *data = [NSMutableDictionary dictionary]; + for (NSObject *key in message) { + if ([key isKindOfClass:[NSString class]]) { + NSString *keyString = (NSString *)key; + if ([keyString isEqualToString:kFIRMessagingContextManagerContentAvailableKey]) { + continue; + } else if ([keyString hasPrefix:kContextManagerPrefixKey]) { + continue; + } + } + data[[key copy]] = message[key]; + } + return [data copy]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.h new file mode 100644 index 0000000..cf8df74 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.h @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GtalkDataMessageStanza; + +@class FIRMessagingClient; +@class FIRMessagingConnection; +@class FIRMessagingReceiver; +@class FIRMessagingRmqManager; +@class FIRMessagingSyncMessageManager; + +@protocol FIRMessagingDataMessageManagerDelegate + +#pragma mark - Downstream Callbacks + +/** + * Invoked when FIRMessaging receives a downstream message via the MCS connection. + * Let's the user know that they have received a new message by invoking the + * App's remoteNotification callback. + * + * @param message The downstream message received by the MCS connection. + */ +- (void)didReceiveMessage:(nonnull NSDictionary *)message + withIdentifier:(nullable NSString *)messageID; + +#pragma mark - Upstream Callbacks + +/** + * Notify the app that FIRMessaging will soon be sending the upstream message requested by the app. + * + * @param messageID The messageId passed in by the app to track this particular message. + * @param error The error in case FIRMessaging cannot send the message upstream. + */ +- (void)willSendDataMessageWithID:(nullable NSString *)messageID error:(nullable NSError *)error; + +/** + * Notify the app that FIRMessaging did successfully send it's message via the MCS + * connection and the message was successfully delivered. + * + * @param messageId The messageId passed in by the app to track this particular + * message. + */ +- (void)didSendDataMessageWithID:(nonnull NSString *)messageId; + +#pragma mark - Server Callbacks + +/** + * Notify the app that FIRMessaging server deleted some messages which exceeded storage limits. This + * indicates the "deleted_messages" message type we received from the server. + */ +- (void)didDeleteMessagesOnServer; + +@end + +/** + * This manages all of the data messages being sent by the client and also the messages that + * were received from the server. + */ +@interface FIRMessagingDataMessageManager : NSObject + +NS_ASSUME_NONNULL_BEGIN + +- (instancetype)initWithDelegate:(id)delegate + client:(FIRMessagingClient *)client + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + syncMessageManager:(FIRMessagingSyncMessageManager *)syncMessageManager; + +- (void)setDeviceAuthID:(NSString *)deviceAuthID secretToken:(NSString *)secretToken; + +- (void)refreshDelayedMessages; + +#pragma mark - Receive + +- (nullable NSDictionary *)processPacket:(GtalkDataMessageStanza *)packet; +- (void)didReceiveParsedMessage:(NSDictionary *)message; + +#pragma mark - Send + +- (void)sendDataMessageStanza:(NSMutableDictionary *)dataMessage; +- (void)didSendDataMessageStanza:(GtalkDataMessageStanza *)message; + +- (void)resendMessagesWithConnection:(FIRMessagingConnection *)connection; + +NS_ASSUME_NONNULL_END + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.m new file mode 100644 index 0000000..b62763a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDataMessageManager.m @@ -0,0 +1,528 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingDataMessageManager.h" + +#import "Protos/GtalkCore.pbobjc.h" + +#import "FIRMessagingClient.h" +#import "FIRMessagingConnection.h" +#import "FIRMessagingConstants.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingDelayedMessageQueue.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingReceiver.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessaging_Private.h" +#import "FIRMessagingSyncMessageManager.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +static const int kMaxAppDataSizeDefault = 4 * 1024; // 4k +static const int kMinDelaySeconds = 1; // 1 second +static const int kMaxDelaySeconds = 60 * 60; // 1 hour + +static NSString *const kFromForFIRMessagingMessages = @"mcs.android.com"; +static NSString *const kGSFMessageCategory = @"com.google.android.gsf.gtalkservice"; +// TODO: Update Gcm to FIRMessaging in the constants below +static NSString *const kFCMMessageCategory = @"com.google.gcm"; +static NSString *const kMessageReservedPrefix = @"google."; + +static NSString *const kFCMMessageSpecialMessage = @"message_type"; + +// special messages sent by the server +static NSString *const kFCMMessageTypeDeletedMessages = @"deleted_messages"; + +static NSString *const kMCSNotificationPrefix = @"gcm.notification."; +static NSString *const kDataMessageNotificationKey = @"notification"; + + +typedef NS_ENUM(int8_t, UpstreamForceReconnect) { + // Never force reconnect on upstream messages + kUpstreamForceReconnectOff = 0, + // Force reconnect for TTL=0 upstream messages + kUpstreamForceReconnectTTL0 = 1, + // Force reconnect for all upstream messages + kUpstreamForceReconnectAll = 2, +}; + +@interface FIRMessagingDataMessageManager () + +@property(nonatomic, readwrite, weak) FIRMessagingClient *client; +@property(nonatomic, readwrite, weak) FIRMessagingRmqManager *rmq2Manager; +@property(nonatomic, readwrite, weak) FIRMessagingSyncMessageManager *syncMessageManager; +@property(nonatomic, readwrite, weak) id delegate; +@property(nonatomic, readwrite, strong) FIRMessagingDelayedMessageQueue *delayedMessagesQueue; + +@property(nonatomic, readwrite, assign) int ttl; +@property(nonatomic, readwrite, copy) NSString *deviceAuthID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, assign) int maxAppDataSize; +@property(nonatomic, readwrite, assign) UpstreamForceReconnect upstreamForceReconnect; + +@end + +@implementation FIRMessagingDataMessageManager + +- (instancetype)initWithDelegate:(id)delegate + client:(FIRMessagingClient *)client + rmq2Manager:(FIRMessagingRmqManager *)rmq2Manager + syncMessageManager:(FIRMessagingSyncMessageManager *)syncMessageManager { + self = [super init]; + if (self) { + _delegate = delegate; + _client = client; + _rmq2Manager = rmq2Manager; + _syncMessageManager = syncMessageManager; + _ttl = kFIRMessagingSendTtlDefault; + _maxAppDataSize = kMaxAppDataSizeDefault; + // on by default + _upstreamForceReconnect = kUpstreamForceReconnectAll; + } + return self; +} + +- (void)setDeviceAuthID:(NSString *)deviceAuthID secretToken:(NSString *)secretToken { + _FIRMessagingDevAssert([deviceAuthID length] && [secretToken length], + @"Invalid credentials for FIRMessaging"); + self.deviceAuthID = deviceAuthID; + self.secretToken = secretToken; +} + +- (void)refreshDelayedMessages { + FIRMessaging_WEAKIFY(self); + self.delayedMessagesQueue = + [[FIRMessagingDelayedMessageQueue alloc] initWithRmqScanner:self.rmq2Manager + sendDelayedMessagesHandler:^(NSArray *messages) { + FIRMessaging_STRONGIFY(self); + [self sendDelayedMessages:messages]; + }]; +} + +- (nullable NSDictionary *)processPacket:(GtalkDataMessageStanza *)dataMessage { + NSString *category = dataMessage.category; + NSString *from = dataMessage.from; + if ([kFCMMessageCategory isEqualToString:category] || + [kGSFMessageCategory isEqualToString:category]) { + [self handleMCSDataMessage:dataMessage]; + return nil; + } else if ([kFromForFIRMessagingMessages isEqualToString:from]) { + [self handleMCSDataMessage:dataMessage]; + return nil; + } + + return [self parseDataMessage:dataMessage]; +} + +- (void)handleMCSDataMessage:(GtalkDataMessageStanza *)dataMessage { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager000, + @"Received message for FIRMessaging from downstream %@", dataMessage); +} + +- (NSDictionary *)parseDataMessage:(GtalkDataMessageStanza *)dataMessage { + NSMutableDictionary *message = [NSMutableDictionary dictionary]; + NSString *from = [dataMessage from]; + if ([from length]) { + message[kFIRMessagingFromKey] = from; + } + + // raw data + NSData *rawData = [dataMessage rawData]; + if ([rawData length]) { + message[kFIRMessagingRawDataKey] = rawData; + } + + NSString *token = [dataMessage token]; + if ([token length]) { + message[kFIRMessagingCollapseKey] = token; + } + + // Add the persistent_id. This would be removed later before sending the message to the device. + NSString *persistentID = [dataMessage persistentId]; + _FIRMessagingDevAssert([persistentID length], @"Invalid MCS message without persistentID"); + if ([persistentID length]) { + message[kFIRMessagingMessageIDKey] = persistentID; + } + + // third-party data + for (GtalkAppData *item in dataMessage.appDataArray) { + _FIRMessagingDevAssert(item.hasKey && item.hasValue, @"Invalid AppData"); + + // do not process the "from" key -- is not useful + if ([kFIRMessagingFromKey isEqualToString:item.key]) { + continue; + } + + // Filter the "gcm.notification." keys in the message + if ([item.key hasPrefix:kMCSNotificationPrefix]) { + NSString *key = [item.key substringFromIndex:[kMCSNotificationPrefix length]]; + if ([key length]) { + if (!message[kDataMessageNotificationKey]) { + message[kDataMessageNotificationKey] = [NSMutableDictionary dictionary]; + } + message[kDataMessageNotificationKey][key] = item.value; + } else { + _FIRMessagingDevAssert([key length], @"Invalid key in MCS message: %@", key); + FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager001, + @"Invalid key in MCS message: %@", key); + } + continue; + } + + // Filter the "gcm.duplex" key + if ([item.key isEqualToString:kFIRMessagingMessageSyncViaMCSKey]) { + BOOL value = [item.value boolValue]; + message[kFIRMessagingMessageSyncViaMCSKey] = @(value); + continue; + } + + // do not allow keys with "reserved" keyword + if ([[item.key lowercaseString] hasPrefix:kMessageReservedPrefix]) { + continue; + } + + [message setObject:item.value forKey:item.key]; + } + // TODO: Add support for encrypting raw data later + return [NSDictionary dictionaryWithDictionary:message]; +} + +- (void)didReceiveParsedMessage:(NSDictionary *)message { + if ([message[kFCMMessageSpecialMessage] length]) { + NSString *messageType = message[kFCMMessageSpecialMessage]; + if ([kFCMMessageTypeDeletedMessages isEqualToString:messageType]) { + // TODO: Maybe trim down message to remove some unnecessary fields. + // tell the FCM receiver of deleted messages + [self.delegate didDeleteMessagesOnServer]; + return; + } + FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager002, + @"Invalid message type received: %@", messageType); + } else if (message[kFIRMessagingMessageSyncViaMCSKey]) { + // Update SYNC_RMQ with the message + BOOL isDuplicate = [self.syncMessageManager didReceiveMCSSyncMessage:message]; + if (isDuplicate) { + return; + } + } + NSString *messageId = message[kFIRMessagingMessageIDKey]; + NSDictionary *filteredMessage = [self filterInternalFIRMessagingKeysFromMessage:message]; + [self.delegate didReceiveMessage:filteredMessage withIdentifier:messageId]; +} + +- (NSDictionary *)filterInternalFIRMessagingKeysFromMessage:(NSDictionary *)message { + NSMutableDictionary *newMessage = [NSMutableDictionary dictionaryWithDictionary:message]; + for (NSString *key in message) { + if ([key hasPrefix:kFIRMessagingMessageInternalReservedKeyword]) { + [newMessage removeObjectForKey:key]; + } + } + return [newMessage copy]; +} + +- (void)sendDataMessageStanza:(NSMutableDictionary *)dataMessage { + NSNumber *ttlNumber = dataMessage[kFIRMessagingSendTTL]; + NSString *to = dataMessage[kFIRMessagingSendTo]; + NSString *msgId = dataMessage[kFIRMessagingSendMessageID]; + NSString *appPackage = [self categoryForUpstreamMessages]; + GtalkDataMessageStanza *stanza = [[GtalkDataMessageStanza alloc] init]; + + // TODO: enforce TTL (right now only ttl=0 is special, means no storage) + int ttl = [ttlNumber intValue]; + if (ttl < 0 || ttl > self.ttl) { + ttl = self.ttl; + } + [stanza setTtl:ttl]; + [stanza setSent:FIRMessagingCurrentTimestampInSeconds()]; + + int delay = [self delayForMessage:dataMessage]; + if (delay > 0) { + [stanza setMaxDelay:delay]; + } + + if (msgId) { + [stanza setId_p:msgId]; + } + + // collapse key as given by the sender + NSString *token = dataMessage[KFIRMessagingSendMessageAppData][kFIRMessagingCollapseKey]; + if ([token length]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager003, + @"FIRMessaging using %@ as collapse key", token); + [stanza setToken:token]; + } + + if (!self.secretToken) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager004, + @"Trying to send data message without a secret token. " + @"Authentication failed."); + [self willSendDataMessageFail:stanza + withMessageId:msgId + error:kFIRMessagingErrorCodeMissingDeviceID]; + return; + } + + if (![to length]) { + [self willSendDataMessageFail:stanza withMessageId:msgId error:kFIRMessagingErrorMissingTo]; + return; + } + [stanza setTo:to]; + [stanza setCategory:appPackage]; + // required field in the proto this is set by the server + // set it to a sentinel so the runtime doesn't throw an exception + [stanza setFrom:@""]; + + // MCS itself would set the registration ID + // [stanza setRegId:nil]; + + int size = [self addData:dataMessage[KFIRMessagingSendMessageAppData] toStanza:stanza]; + if (size > kMaxAppDataSizeDefault) { + [self willSendDataMessageFail:stanza withMessageId:msgId error:kFIRMessagingErrorSizeExceeded]; + return; + } + + BOOL useRmq = (ttl != 0) && (msgId != nil); + if (useRmq) { + if (!self.client.isConnected) { + // do nothing assuming rmq save is enabled + } + + NSError *error; + if (![self.rmq2Manager saveRmqMessage:stanza error:&error]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager005, @"%@", error); + [self willSendDataMessageFail:stanza withMessageId:msgId error:kFIRMessagingErrorSave]; + return; + } + + [self willSendDataMessageSuccess:stanza withMessageId:msgId]; + } + + // if delay > 0 we don't really care about sending the message right now + // so we piggy-back on any other urgent(delay = 0) message that we are sending + if (delay > 0 && [self delayMessage:stanza]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager006, @"Delaying Message %@", + dataMessage); + return; + } + // send delayed messages + [self sendDelayedMessages:[self.delayedMessagesQueue removeDelayedMessages]]; + + BOOL sending = [self tryToSendDataMessageStanza:stanza]; + if (!sending) { + if (useRmq) { + NSString *event __unused = [NSString stringWithFormat:@"Queued message: %@", [stanza id_p]]; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager007, @"%@", event); + } else { + [self willSendDataMessageFail:stanza + withMessageId:msgId + error:kFIRMessagingErrorCodeNetwork]; + return; + } + } +} + +- (void)sendDelayedMessages:(NSArray *)delayedMessages { + for (GtalkDataMessageStanza *message in delayedMessages) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager008, + @"%@ Sending delayed message %@", @"DMM", message); + [message setActualDelay:(int)(FIRMessagingCurrentTimestampInSeconds() - message.sent)]; + [self tryToSendDataMessageStanza:message]; + } +} + +- (void)didSendDataMessageStanza:(GtalkDataMessageStanza *)message { + NSString *msgId = [message id_p] ?: @""; + [self.delegate didSendDataMessageWithID:msgId]; +} + +- (void)addParamWithKey:(NSString *)key + value:(NSString *)val + toStanza:(GtalkDataMessageStanza *)stanza { + if (!key || !val) { + return; + } + GtalkAppData *appData = [[GtalkAppData alloc] init]; + [appData setKey:key]; + [appData setValue:val]; + [[stanza appDataArray] addObject:appData]; +} + +/** + @return The size of the data being added to stanza. + */ +- (int)addData:(NSDictionary *)data toStanza:(GtalkDataMessageStanza *)stanza { + int size = 0; + for (NSString *key in data) { + NSObject *val = data[key]; + if ([val isKindOfClass:[NSString class]]) { + NSString *strVal = (NSString *)val; + [self addParamWithKey:key value:strVal toStanza:stanza]; + size += [key length] + [strVal length]; + } else if ([val isKindOfClass:[NSNumber class]]) { + NSString *strVal = [(NSNumber *)val stringValue]; + [self addParamWithKey:key value:strVal toStanza:stanza]; + size += [key length] + [strVal length]; + } else if ([kFIRMessagingRawDataKey isEqualToString:key] && + [val isKindOfClass:[NSData class]]) { + NSData *rawData = (NSData *)val; + [stanza setRawData:[rawData copy]]; + size += [rawData length]; + } else { + FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager009, @"Ignoring key: %@", + key); + } + } + return size; +} + +/** + * Notify the messenger that send data message completed with success. This is called for + * TTL=0, after the message has been sent, or when message is saved, to unlock the send() + * method. + */ +- (void)willSendDataMessageSuccess:(GtalkDataMessageStanza *)stanza + withMessageId:(NSString *)messageId { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager010, + @"send message success: %@", messageId); + [self.delegate willSendDataMessageWithID:messageId error:nil]; +} + +/** + * We send 'send failures' from server as normal FIRMessaging messages, with a 'message_type' + * extra - same as 'message deleted'. + * + * For TTL=0 or errors that can be detected during send ( too many messages, invalid, etc) + * we throw IOExceptions + */ +- (void)willSendDataMessageFail:(GtalkDataMessageStanza *)stanza + withMessageId:(NSString *)messageId + error:(FIRMessagingInternalErrorCode)errorCode { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager011, + @"Send message fail: %@ error: %lu", messageId, (unsigned long)errorCode); + + NSError *error = [NSError errorWithFCMErrorCode:errorCode]; + if ([self.delegate respondsToSelector:@selector(willSendDataMessageWithID:error:)]) { + [self.delegate willSendDataMessageWithID:messageId error:error]; + } +} + +- (void)resendMessagesWithConnection:(FIRMessagingConnection *)connection { + NSMutableString *rmqIdsResent = [NSMutableString string]; + NSMutableArray *toRemoveRmqIds = [NSMutableArray array]; + FIRMessaging_WEAKIFY(self); + FIRMessaging_WEAKIFY(connection); + FIRMessagingRmqMessageHandler messageHandler = ^(int64_t rmqId, int8_t tag, NSData *data) { + FIRMessaging_STRONGIFY(self); + FIRMessaging_STRONGIFY(connection); + GPBMessage *proto = + [FIRMessagingGetClassForTag((FIRMessagingProtoTag)tag) parseFromData:data error:NULL]; + if ([proto isKindOfClass:GtalkDataMessageStanza.class]) { + GtalkDataMessageStanza *stanza = (GtalkDataMessageStanza *)proto; + + if (![self handleExpirationForDataMessage:stanza]) { + // time expired let's delete from RMQ + [toRemoveRmqIds addObject:stanza.persistentId]; + return; + } + [rmqIdsResent appendString:[NSString stringWithFormat:@"%@,", stanza.id_p]]; + } + + [connection sendProto:proto]; + }; + [self.rmq2Manager scanWithRmqMessageHandler:messageHandler + dataMessageHandler:nil]; + + if ([rmqIdsResent length]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeDataMessageManager012, @"Resent: %@", + rmqIdsResent); + } + + if ([toRemoveRmqIds count]) { + [self.rmq2Manager removeRmqMessagesWithRmqIds:toRemoveRmqIds]; + } +} + +/** + * Check the TTL and generate an error if needed. + * + * @return false if the message needs to be deleted + */ +- (BOOL)handleExpirationForDataMessage:(GtalkDataMessageStanza *)message { + if (message.ttl == 0) { + return NO; + } + + int64_t now = FIRMessagingCurrentTimestampInSeconds(); + if (now > message.sent + message.ttl) { + [self willSendDataMessageFail:message + withMessageId:message.id_p + error:kFIRMessagingErrorServiceNotAvailable]; + return NO; + } + return YES; +} + +#pragma mark - Private + +- (int)delayForMessage:(NSMutableDictionary *)message { + int delay = 0; // default + if (message[kFIRMessagingSendDelay]) { + delay = [message[kFIRMessagingSendDelay] intValue]; + [message removeObjectForKey:kFIRMessagingSendDelay]; + if (delay < kMinDelaySeconds) { + delay = 0; + } else if (delay > kMaxDelaySeconds) { + delay = kMaxDelaySeconds; + } + } + return delay; +} + +// return True if successfully delayed else False +- (BOOL)delayMessage:(GtalkDataMessageStanza *)message { + return [self.delayedMessagesQueue queueMessage:message]; +} + +- (BOOL)tryToSendDataMessageStanza:(GtalkDataMessageStanza *)stanza { + if (self.client.isConnectionActive) { + [self.client sendMessage:stanza]; + return YES; + } + + // if we only reconnect for TTL = 0 messages check if we ttl = 0 or + // if we reconnect for all messages try to reconnect + if ((self.upstreamForceReconnect == kUpstreamForceReconnectTTL0 && stanza.ttl == 0) || + self.upstreamForceReconnect == kUpstreamForceReconnectAll) { + BOOL isNetworkAvailable = [[FIRMessaging messaging] isNetworkAvailable]; + if (isNetworkAvailable) { + if (stanza.ttl == 0) { + // Add TTL = 0 messages to be sent on next connect. TTL != 0 messages are + // persisted, and will be sent from the RMQ. + [self.client sendOnConnectOrDrop:stanza]; + } + + [self.client retryConnectionImmediately:YES]; + return YES; + } + } + return NO; +} + +- (NSString *)categoryForUpstreamMessages { + return FIRMessagingAppIdentifier(); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDefines.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDefines.h new file mode 100644 index 0000000..abf79a5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDefines.h @@ -0,0 +1,84 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRMessaging_xcodeproj_FIRMessagingDefines_h +#define FIRMessaging_xcodeproj_FIRMessagingDefines_h + +#define _FIRMessaging_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRMessaging_VERBOSE_LOGGING) +#define FIRMessaging_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRMessaging_DEV_VERBOSE_LOG(...) do { } while (0) +#endif // FIRMessaging_VERBOSE_LOGGING + + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRMessaging_WEAKNAME(VAR) VAR ## _weak_ + +#define FIRMessaging_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRMessaging_WEAKNAME(VAR) = (VAR); + +#define FIRMessaging_STRONGIFY(VAR) \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wshadow\"") \ +__strong __typeof__(VAR) VAR = _FIRMessaging_WEAKNAME(VAR); \ +_Pragma("clang diagnostic pop") + + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRMessaging_L +#define _FIRMessaging_L(v) (long)(v) +#endif + +#ifndef _FIRMessaging_UL +#define _FIRMessaging_UL(v) (unsigned long)(v) +#endif + +#endif + +// Debug Assert +#ifndef _FIRMessagingDevAssert +// we directly invoke the NSAssert handler so we can pass on the varargs +// (NSAssert doesn't have a macro we can use that takes varargs) +#ifdef DEBUG +#define _FIRMessagingDevAssert(condition, ...) \ + do { \ + if (!(condition)) { \ + [[NSAssertionHandler currentHandler] \ + handleFailureInFunction:(NSString *) \ + [NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ + file:(NSString *)[NSString stringWithUTF8String:__FILE__] \ + lineNumber:__LINE__ \ + description:__VA_ARGS__]; \ + } \ + } while(0) +#else // !defined(DEBUG) +#define _FIRMessagingDevAssert(condition, ...) do { } while (0) +#endif // !defined(DEBUG) + +#endif // _FIRMessagingDevAssert + +// Invalidates the initializer from which it's called. +#ifndef FIRMessagingInvalidateInitializer +#define FIRMessagingInvalidateInitializer() \ + do { \ + [self class]; /* Avoid warning of dead store to |self|. */ \ + _FIRMessagingDevAssert(NO, @"Invalid initializer."); \ + return nil; \ + } while (0) +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.h new file mode 100644 index 0000000..d20ec91 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GtalkDataMessageStanza; +@class FIRMessagingRmqManager; + +@protocol FIRMessagingRmqScanner; + +typedef void(^FIRMessagingSendDelayedMessagesHandler)(NSArray *messages); + +@interface FIRMessagingDelayedMessageQueue : NSObject + +- (instancetype)initWithRmqScanner:(id)rmqScanner + sendDelayedMessagesHandler:(FIRMessagingSendDelayedMessagesHandler)sendDelayedMessagesHandler; + +- (BOOL)queueMessage:(GtalkDataMessageStanza *)message; + +- (NSArray *)removeDelayedMessages; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.m new file mode 100644 index 0000000..0371c02 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingDelayedMessageQueue.m @@ -0,0 +1,146 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingDelayedMessageQueue.h" + +#import "Protos/GtalkCore.pbobjc.h" + +#import "FIRMessagingDefines.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingUtilities.h" + +static const int kMaxQueuedMessageCount = 10; + +@interface FIRMessagingDelayedMessageQueue () + +@property(nonatomic, readonly, weak) id rmqScanner; +@property(nonatomic, readonly, copy) FIRMessagingSendDelayedMessagesHandler sendDelayedMessagesHandler; + +@property(nonatomic, readwrite, assign) int persistedMessageCount; +// the scheduled timeout or -1 if not set +@property(nonatomic, readwrite, assign) int64_t scheduledTimeoutMilliseconds; +// The time of the last scan of the message DB, +// used to avoid retrieving messages more than once. +@property(nonatomic, readwrite, assign) int64_t lastDBScanTimestampSeconds; + +@property(nonatomic, readwrite, strong) NSMutableArray *messages; +@property(nonatomic, readwrite, strong) NSTimer *sendTimer; + +@end + +@implementation FIRMessagingDelayedMessageQueue + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithRmqScanner:(id)rmqScanner + sendDelayedMessagesHandler:(FIRMessagingSendDelayedMessagesHandler)sendDelayedMessagesHandler { + _FIRMessagingDevAssert(sendDelayedMessagesHandler, @"Invalid nil callback for delayed messages"); + self = [super init]; + if (self) { + _rmqScanner = rmqScanner; + _sendDelayedMessagesHandler = sendDelayedMessagesHandler; + _messages = [NSMutableArray arrayWithCapacity:10]; + _scheduledTimeoutMilliseconds = -1; + } + return self; +} + +- (BOOL)queueMessage:(GtalkDataMessageStanza *)message { + if (self.messages.count >= kMaxQueuedMessageCount) { + return NO; + } + if (message.ttl == 0) { + // ttl=0 messages aren't persisted, add it to memory + [self.messages addObject:message]; + } else { + self.persistedMessageCount++; + } + int64_t timeoutMillis = [self calculateTimeoutInMillisWithDelayInSeconds:message.maxDelay]; + if (![self isTimeoutScheduled] || timeoutMillis < self.scheduledTimeoutMilliseconds) { + [self scheduleTimeoutInMillis:timeoutMillis]; + } + return YES; +} + +- (NSArray *)removeDelayedMessages { + [self cancelTimeout]; + if ([self messageCount] == 0) { + return @[]; + } + + NSMutableArray *delayedMessages = [NSMutableArray array]; + // add the ttl=0 messages + if (self.messages.count) { + [delayedMessages addObjectsFromArray:delayedMessages]; + [self.messages removeAllObjects]; + } + + // add persistent messages + if (self.persistedMessageCount > 0) { + FIRMessaging_WEAKIFY(self); + [self.rmqScanner scanWithRmqMessageHandler:nil + dataMessageHandler:^(int64_t rmqId, GtalkDataMessageStanza *stanza) { + FIRMessaging_STRONGIFY(self); + if ([stanza hasMaxDelay] && + [stanza sent] >= self.lastDBScanTimestampSeconds) { + [delayedMessages addObject:stanza]; + } + }]; + self.lastDBScanTimestampSeconds = FIRMessagingCurrentTimestampInSeconds(); + self.persistedMessageCount = 0; + } + return delayedMessages; +} + +- (void)sendMessages { + if (self.sendDelayedMessagesHandler) { + self.sendDelayedMessagesHandler([self removeDelayedMessages]); + } +} + +#pragma mark - Private + +- (NSInteger)messageCount { + return self.messages.count + self.persistedMessageCount; +} + +- (BOOL)isTimeoutScheduled { + return self.scheduledTimeoutMilliseconds > 0; +} + +- (int64_t)calculateTimeoutInMillisWithDelayInSeconds:(int)delay { + return FIRMessagingCurrentTimestampInMilliseconds() + delay * 1000.0; +} + +- (void)scheduleTimeoutInMillis:(int64_t)time { + [self cancelTimeout]; + self.scheduledTimeoutMilliseconds = time; + double delay = (time - FIRMessagingCurrentTimestampInMilliseconds()) / 1000.0; + [self performSelector:@selector(sendMessages) withObject:self afterDelay:delay]; +} + +- (void)cancelTimeout { + if ([self isTimeoutScheduled]) { + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(sendMessages) + object:nil]; + self.scheduledTimeoutMilliseconds = -1; + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingExtensionHelper.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingExtensionHelper.m new file mode 100644 index 0000000..7b436e3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingExtensionHelper.m @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + #import "FIRMessagingExtensionHelper.h" + + #import "FIRMMessageCode.h" +#import "FIRMessagingLogger.h" + + static NSString *const kPayloadOptionsName = @"fcm_options"; +static NSString *const kPayloadOptionsImageURLName = @"image"; + + @interface FIRMessagingExtensionHelper () +@property(nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver); +@property(nonatomic, strong) UNMutableNotificationContent *bestAttemptContent; + + @end + + @implementation FIRMessagingExtensionHelper + + - (void)populateNotificationContent:(UNMutableNotificationContent *)content + withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler { + self.contentHandler = [contentHandler copy]; + self.bestAttemptContent = content; + + NSString *currentImageURL = content.userInfo[kPayloadOptionsName][kPayloadOptionsImageURLName]; + if (!currentImageURL) { + [self deliverNotification]; + return; + } +#if TARGET_OS_IOS + NSURL *attachmentURL = [NSURL URLWithString:currentImageURL]; + if (attachmentURL) { + [self loadAttachmentForURL:attachmentURL + completionHandler:^(UNNotificationAttachment *attachment) { + self.bestAttemptContent.attachments = @[ attachment ]; + [self deliverNotification]; + }]; + } else { + FIRMessagingLoggerError(kFIRMessagingServiceExtensionImageInvalidURL, + @"The Image URL provided is invalid %@.", currentImageURL); + [self deliverNotification]; + } +#else + [self deliverNotification]; +#endif +} + + #if TARGET_OS_IOS +- (void)loadAttachmentForURL:(NSURL *)attachmentURL + completionHandler:(void (^)(UNNotificationAttachment *))completionHandler { + __block UNNotificationAttachment *attachment = nil; + + NSURLSession *session = [NSURLSession + sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + [[session + downloadTaskWithURL:attachmentURL + completionHandler:^(NSURL *temporaryFileLocation, NSURLResponse *response, NSError *error) { + if (error != nil) { + FIRMessagingLoggerError(kFIRMessagingServiceExtensionImageNotDownloaded, + @"Failed to download image given URL %@, error: %@\n", + attachmentURL, error); + completionHandler(attachment); + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *fileExtension = + [NSString stringWithFormat:@".%@", [response.suggestedFilename pathExtension]]; + NSURL *localURL = [NSURL + fileURLWithPath:[temporaryFileLocation.path stringByAppendingString:fileExtension]]; + [fileManager moveItemAtURL:temporaryFileLocation toURL:localURL error:&error]; + if (error) { + FIRMessagingLoggerError( + kFIRMessagingServiceExtensionLocalFileNotCreated, + @"Failed to move the image file to local location: %@, error: %@\n", localURL, + error); + completionHandler(attachment); + return; + } + + attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" + URL:localURL + options:nil + error:&error]; + if (error) { + FIRMessagingLoggerError(kFIRMessagingServiceExtensionImageNotAttached, + @"Failed to create attachment with URL %@, error: %@\n", + localURL, error); + completionHandler(attachment); + return; + } + completionHandler(attachment); + }] resume]; +} +#endif + + - (void)deliverNotification { + if (self.contentHandler) { + self.contentHandler(self.bestAttemptContent); + } +} + + @end + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.h new file mode 100644 index 0000000..223ac9c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.h @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRMessagingLoggerInfo + +// Convenience macros that log to the shared FIRMessagingLogger instance. These macros +// are how users should typically log to FIRMessagingLogger. +#define FIRMessagingLoggerDebug(code, ...) \ + [FIRMessagingSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerInfo(code, ...) \ + [FIRMessagingSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerNotice(code, ...) \ + [FIRMessagingSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerWarn(code, ...) \ + [FIRMessagingSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRMessagingLoggerError(code, ...) \ + [FIRMessagingSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRMessagingLoggerInfo) + +@interface FIRMessagingLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared FIRMessagingLogger used exclusively + * for FIRMessaging log messages. + * + * @return the shared FIRMessagingLogger instance + */ +FIRMessagingLogger *FIRMessagingSharedLogger(void); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.m new file mode 100644 index 0000000..d3c96d2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingLogger.m @@ -0,0 +1,95 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingLogger.h" + +#import + +FIRLoggerService kFIRLoggerMessaging = @"[Firebase/Messaging]"; + +@implementation FIRMessagingLogger + ++ (instancetype)standardLogger { + return [[FIRMessagingLogger alloc] init]; +} + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRMessagingMessageCode)messageCode { + return [NSString stringWithFormat:@"I-FCM%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRMessagingMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRLoggerMessaging, + [FIRMessagingLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRMessagingLogger *FIRMessagingSharedLogger(void) { + static dispatch_once_t onceToken; + static FIRMessagingLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [FIRMessagingLogger standardLogger]; + }); + + return logger; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.h new file mode 100644 index 0000000..1f528ab --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRMessagingPacket : NSObject + ++ (FIRMessagingPacket *)packetWithTag:(int8_t)tag rmqId:(NSString *)rmqId data:(NSData *)data; + +@property(nonatomic, readonly, strong) NSData *data; +@property(nonatomic, readonly, assign) int8_t tag; +// not sent over the wire required for bookkeeping +@property(nonatomic, readonly, assign) NSString *rmqId; + +@end + + +/** + * A queue of the packets(protos) that need to be send over the wire. + */ +@interface FIRMessagingPacketQueue : NSObject + +@property(nonatomic, readonly, assign) NSUInteger count; +@property(nonatomic, readonly, assign) BOOL isEmpty; + +- (void)push:(FIRMessagingPacket *)packet; +- (void)pushHead:(FIRMessagingPacket *)packet; +- (FIRMessagingPacket *)pop; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.m new file mode 100644 index 0000000..2b3410a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPacketQueue.m @@ -0,0 +1,103 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPacketQueue.h" + +#import "FIRMessagingDefines.h" + +@interface FIRMessagingPacket () + +@property(nonatomic, readwrite, strong) NSData *data; +@property(nonatomic, readwrite, assign) int8_t tag; +@property(nonatomic, readwrite, assign) NSString *rmqId; + +@end + +@implementation FIRMessagingPacket + ++ (FIRMessagingPacket *)packetWithTag:(int8_t)tag rmqId:(NSString *)rmqId data:(NSData *)data { + return [[self alloc] initWithTag:tag rmqId:rmqId data:data]; +} + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithTag:(int8_t)tag rmqId:(NSString *)rmqId data:(NSData *)data { + self = [super init]; + if (self != nil) { + _data = data; + _tag = tag; + _rmqId = rmqId; + } + return self; +} + +- (NSString *)description { + if ([self.rmqId length]) { + return [NSString stringWithFormat:@", RmqId - %@", + self.tag, _FIRMessaging_UL(self.data.length), self.rmqId]; + } else { + return [NSString stringWithFormat:@"", + self.tag, _FIRMessaging_UL(self.data.length)]; + } +} + +@end + +@interface FIRMessagingPacketQueue () + +@property(nonatomic, readwrite, strong) NSMutableArray *packetsContainer; + +@end + + +@implementation FIRMessagingPacketQueue; + +- (id)init { + self = [super init]; + if (self) { + _packetsContainer = [[NSMutableArray alloc] init]; + } + return self; +} + +- (BOOL)isEmpty { + return self.packetsContainer.count == 0; +} + +- (NSUInteger)count { + return self.packetsContainer.count; +} + +- (void)push:(FIRMessagingPacket *)packet { + [self.packetsContainer addObject:packet]; +} + +- (void)pushHead:(FIRMessagingPacket *)packet { + [self.packetsContainer insertObject:packet atIndex:0]; +} + +- (FIRMessagingPacket *)pop { + if (!self.isEmpty) { + FIRMessagingPacket *packet = self.packetsContainer[0]; + [self.packetsContainer removeObjectAtIndex:0]; + return packet; + } + return nil; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.h new file mode 100644 index 0000000..a8108bf --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingTopicsCommon.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents a single batch of topics, with the same action. + * + * Topic operations which have the same action (subscribe or unsubscribe) can be executed + * simultaneously, as the order of operations do not matter with the same action. The set of + * topics is unique, as it doesn't make sense to apply the same action to the same topic + * repeatedly; the result would be the same as the first time. + */ +@interface FIRMessagingTopicBatch : NSObject + +@property(nonatomic, readonly, assign) FIRMessagingTopicAction action; +@property(nonatomic, readonly, copy) NSMutableSet *topics; + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithAction:(FIRMessagingTopicAction)action NS_DESIGNATED_INITIALIZER; + +@end + +@class FIRMessagingPendingTopicsList; +/** + * This delegate must be supplied to the instance of FIRMessagingPendingTopicsList, via the + * @cdelegate property. It lets the + * pending topics list know whether or not it can begin making requests via + * @c-pendingTopicsListCanRequestTopicUpdates:, and handles the request to actually + * perform the topic operation. The delegate also handles when the pending topics list is updated, + * so that it can be archived or persisted. + * + * @see FIRMessagingPendingTopicsList + */ +@protocol FIRMessagingPendingTopicsListDelegate + +- (void)pendingTopicsList:(FIRMessagingPendingTopicsList *)list + requestedUpdateForTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + completion:(FIRMessagingTopicOperationCompletion)completion; +- (void)pendingTopicsListDidUpdate:(FIRMessagingPendingTopicsList *)list; +- (BOOL)pendingTopicsListCanRequestTopicUpdates:(FIRMessagingPendingTopicsList *)list; + +@end + +/** + * FIRMessagingPendingTopicsList manages a list of topic subscription updates, batched by the same + * action (subscribe or unsubscribe). The list roughly maintains the order of the topic operations, + * batched together whenever the topic action (subscribe or unsubscribe) changes. + * + * Topics operations are batched by action because it is safe to perform the same topic action + * (subscribe or unsubscribe) on many topics simultaneously. After each batch is successfully + * completed, the next batch operations can begin. + * + * When asked to resume its operations, FIRMessagingPendingTopicsList will begin performing updates + * of its current batch of topics. For example, it may begin subscription operations for topics + * [A, B, C] simultaneously. + * + * When the current batch is completed, the next batch of operations will be started. For example + * the list may begin unsubscribe operations for [D, A, E]. Note that because A is in both batches, + * A will be correctly subscribed in the first batch, then unsubscribed as part of the second batch + * of operations. Without batching, it would be ambiguous whether A's subscription operation or the + * unsubscription operation would be completed first. + * + * An app can subscribe and unsubscribe from many topics, and this class helps persist the pending + * topics and perform the operation safely and correctly. + * + * When a topic fails to subscribe or unsubscribe due to a network error, it is considered a + * recoverable error, and so it remains in the current batch until it is succesfully completed. + * Topic updates are completed when they either (a) succeed, (b) are cancelled, or (c) result in an + * unrecoverable error. Any error outside of `NSURLErrorDomain` is considered an unrecoverable + * error. + * + * In addition to maintaining the list of pending topic updates, FIRMessagingPendingTopicsList also + * can track completion handlers for topic operations. + * + * @discussion Completion handlers for topic updates are not maintained if it was restored from a + * keyed archive. They are only called if the topic operation finished within the same app session. + * + * You must supply an object conforming to FIRMessagingPendingTopicsListDelegate in order for the + * topic operations to execute. + * + * @see FIRMessagingPendingTopicsListDelegate + */ +@interface FIRMessagingPendingTopicsList : NSObject + +@property(nonatomic, weak) NSObject *delegate; + +@property(nonatomic, readonly, strong, nullable) NSDate *archiveDate; +@property(nonatomic, readonly) NSUInteger numberOfBatches; + + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (void)addOperationForTopic:(NSString *)topic + withAction:(FIRMessagingTopicAction)action + completion:(nullable FIRMessagingTopicOperationCompletion)completion; +- (void)resumeOperationsIfNeeded; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.m new file mode 100644 index 0000000..b10b552 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPendingTopicsList.m @@ -0,0 +1,265 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPendingTopicsList.h" + +#import "FIRMessaging_Private.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPubSub.h" + +#import "FIRMessagingDefines.h" + +NSString *const kPendingTopicBatchActionKey = @"action"; +NSString *const kPendingTopicBatchTopicsKey = @"topics"; + +NSString *const kPendingBatchesEncodingKey = @"batches"; +NSString *const kPendingTopicsTimestampEncodingKey = @"ts"; + +#pragma mark - FIRMessagingTopicBatch + +@interface FIRMessagingTopicBatch () + +@property(nonatomic, strong, nonnull) NSMutableDictionary + *> *topicHandlers; + +@end + +@implementation FIRMessagingTopicBatch + +- (instancetype)initWithAction:(FIRMessagingTopicAction)action { + if (self = [super init]) { + _action = action; + _topics = [NSMutableSet set]; + _topicHandlers = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark NSCoding + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInteger:self.action forKey:kPendingTopicBatchActionKey]; + [aCoder encodeObject:self.topics forKey:kPendingTopicBatchTopicsKey]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + + // Ensure that our integer -> enum casting is safe + NSInteger actionRawValue = [aDecoder decodeIntegerForKey:kPendingTopicBatchActionKey]; + FIRMessagingTopicAction action = FIRMessagingTopicActionSubscribe; + if (actionRawValue == FIRMessagingTopicActionUnsubscribe) { + action = FIRMessagingTopicActionUnsubscribe; + } + + if (self = [self initWithAction:action]) { + NSSet *topics = [aDecoder decodeObjectForKey:kPendingTopicBatchTopicsKey]; + if ([topics isKindOfClass:[NSSet class]]) { + _topics = [topics mutableCopy]; + } + _topicHandlers = [NSMutableDictionary dictionary]; + } + return self; +} + +@end + +#pragma mark - FIRMessagingPendingTopicsList + +@interface FIRMessagingPendingTopicsList () + +@property(nonatomic, readwrite, strong) NSDate *archiveDate; +@property(nonatomic, strong) NSMutableArray *topicBatches; + +@property(nonatomic, strong) FIRMessagingTopicBatch *currentBatch; +@property(nonatomic, strong) NSMutableSet *topicsInFlight; + +@end + +@implementation FIRMessagingPendingTopicsList + +- (instancetype)init { + if (self = [super init]) { + _topicBatches = [NSMutableArray array]; + _topicsInFlight = [NSMutableSet set]; + } + return self; +} + ++ (void)pruneTopicBatches:(NSMutableArray *)topicBatches { + // For now, just remove empty batches. In the future we can use this to make the subscriptions + // more efficient, by actually pruning topic actions that cancel each other out, for example. + for (NSInteger i = topicBatches.count-1; i >= 0; i--) { + FIRMessagingTopicBatch *batch = topicBatches[i]; + if (batch.topics.count == 0) { + [topicBatches removeObjectAtIndex:i]; + } + } +} + +#pragma mark NSCoding + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[NSDate date] forKey:kPendingTopicsTimestampEncodingKey]; + [aCoder encodeObject:self.topicBatches forKey:kPendingBatchesEncodingKey]; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + + if (self = [self init]) { + _archiveDate = [aDecoder decodeObjectForKey:kPendingTopicsTimestampEncodingKey]; + NSArray *archivedBatches = [aDecoder decodeObjectForKey:kPendingBatchesEncodingKey]; + if (archivedBatches) { + _topicBatches = [archivedBatches mutableCopy]; + [FIRMessagingPendingTopicsList pruneTopicBatches:_topicBatches]; + } + _topicsInFlight = [NSMutableSet set]; + } + return self; +} + +#pragma mark Getters + +- (NSUInteger)numberOfBatches { + return self.topicBatches.count; +} + +#pragma mark Adding/Removing topics + +- (void)addOperationForTopic:(NSString *)topic + withAction:(FIRMessagingTopicAction)action + completion:(nullable FIRMessagingTopicOperationCompletion)completion { + + FIRMessagingTopicBatch *lastBatch = nil; + @synchronized (self) { + lastBatch = self.topicBatches.lastObject; + if (!lastBatch || lastBatch.action != action) { + // There either was no last batch, or our last batch's action was not the same, so we have to + // create a new batch + lastBatch = [[FIRMessagingTopicBatch alloc] initWithAction:action]; + [self.topicBatches addObject:lastBatch]; + } + BOOL topicExistedBefore = ([lastBatch.topics member:topic] != nil); + if (!topicExistedBefore) { + [lastBatch.topics addObject:topic]; + [self.delegate pendingTopicsListDidUpdate:self]; + } + // Add the completion handler to the batch + if (completion) { + NSMutableArray *handlers = lastBatch.topicHandlers[topic]; + if (!handlers) { + handlers = [[NSMutableArray alloc] init]; + } + [handlers addObject:completion]; + lastBatch.topicHandlers[topic] = handlers; + } + if (!self.currentBatch) { + self.currentBatch = lastBatch; + } + // This may have been the first topic added, or was added to an ongoing batch + if (self.currentBatch == lastBatch && !topicExistedBefore) { + // Add this topic to our ongoing operations + FIRMessaging_WEAKIFY(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + FIRMessaging_STRONGIFY(self); + [self resumeOperationsIfNeeded]; + }); + } + } +} + +- (void)resumeOperationsIfNeeded { + @synchronized (self) { + // If current batch is not set, set it now + if (!self.currentBatch) { + self.currentBatch = self.topicBatches.firstObject; + } + if (self.currentBatch.topics.count == 0) { + return; + } + if (!self.delegate) { + FIRMessagingLoggerError(kFIRMessagingMessageCodePendingTopicsList000, + @"Attempted to update pending topics without a delegate"); + return; + } + if (![self.delegate pendingTopicsListCanRequestTopicUpdates:self]) { + return; + } + for (NSString *topic in self.currentBatch.topics) { + if ([self.topicsInFlight member:topic]) { + // This topic is already active, so skip + continue; + } + [self beginUpdateForCurrentBatchTopic:topic]; + } + } +} + +- (BOOL)subscriptionErrorIsRecoverable:(NSError *)error { + return [error.domain isEqualToString:NSURLErrorDomain]; +} + +- (void)beginUpdateForCurrentBatchTopic:(NSString *)topic { + + @synchronized (self) { + [self.topicsInFlight addObject:topic]; + } + FIRMessaging_WEAKIFY(self); + [self.delegate + pendingTopicsList:self + requestedUpdateForTopic:topic + action:self.currentBatch.action + completion:^(NSError *error) { + dispatch_async( + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + FIRMessaging_STRONGIFY(self); + @synchronized(self) { + [self.topicsInFlight removeObject:topic]; + + BOOL recoverableError = [self subscriptionErrorIsRecoverable:error]; + if (!error || !recoverableError) { + // Notify our handlers and remove the topic from our batch + NSMutableArray *handlers = self.currentBatch.topicHandlers[topic]; + if (handlers.count) { + dispatch_async(dispatch_get_main_queue(), ^{ + for (FIRMessagingTopicOperationCompletion handler in handlers) { + handler(error); + } + [handlers removeAllObjects]; + }); + } + [self.currentBatch.topics removeObject:topic]; + [self.currentBatch.topicHandlers removeObjectForKey:topic]; + if (self.currentBatch.topics.count == 0) { + // All topic updates successfully finished in this batch, move on + // to the next batch + [self.topicBatches removeObject:self.currentBatch]; + self.currentBatch = nil; + } + [self.delegate pendingTopicsListDidUpdate:self]; + FIRMessaging_WEAKIFY(self); + dispatch_async( + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), + ^{ + FIRMessaging_STRONGIFY(self); + [self resumeOperationsIfNeeded]; + }); + } + } + }); + }]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.h new file mode 100644 index 0000000..5a48e99 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRMessagingPersistentSyncMessage : NSObject + +@property(nonatomic, readonly, strong) NSString *rmqID; +@property(nonatomic, readwrite, assign) BOOL apnsReceived; +@property(nonatomic, readwrite, assign) BOOL mcsReceived; +@property(nonatomic, readonly, assign) int64_t expirationTime; + +- (instancetype)initWithRMQID:(NSString *)rmqID expirationTime:(int64_t)expirationTime; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.m new file mode 100644 index 0000000..bf7d05b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPersistentSyncMessage.m @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPersistentSyncMessage.h" + +#import "FIRMessagingDefines.h" + +@interface FIRMessagingPersistentSyncMessage () + +@property(nonatomic, readwrite, strong) NSString *rmqID; +@property(nonatomic, readwrite, assign) int64_t expirationTime; + +@end + +@implementation FIRMessagingPersistentSyncMessage + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithRMQID:(NSString *)rmqID expirationTime:(int64_t)expirationTime { + self = [super init]; + if (self) { + _rmqID = [rmqID copy]; + _expirationTime = expirationTime; + } + return self; +} + +- (NSString *)description { + NSString *classDescription = NSStringFromClass([self class]); + NSDate *date = [NSDate dateWithTimeIntervalSince1970:self.expirationTime]; + return [NSString stringWithFormat:@"%@: (rmqID: %@, apns: %d, mcs: %d, expiry: %@", + classDescription, self.rmqID, self.mcsReceived, self.apnsReceived, date]; +} + +- (NSString *)debugDescription { + return [self description]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.h new file mode 100644 index 0000000..2c2fbe6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.h @@ -0,0 +1,171 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRMessagingClient; +@class FIRMessagingPubSubCache; + +/** + * FIRMessagingPubSub provides a publish-subscribe model for sending FIRMessaging topic messages. + * + * An app can subscribe to different topics defined by the + * developer. The app server can then send messages to the subscribed devices + * without having to maintain topic-subscribers mapping. Topics do not + * need to be explicitly created before subscribing or publishing—they + * are automatically created when publishing or subscribing. + * + * Messages published to the topic will be received as regular FIRMessaging messages + * with `"from"` set to `"/topics/myTopic"`. + * + * Only topic names that match the pattern `"/topics/[a-zA-Z0-9-_.~%]{1,900}"` + * are allowed for subscribing and publishing. + */ +@interface FIRMessagingPubSub : NSObject + +@property(nonatomic, readonly, strong) FIRMessagingPubSubCache *cache; +@property(nonatomic, readonly, strong) FIRMessagingClient *client; + +/** + * Initializes an instance of FIRMessagingPubSub. + * + * @return An instance of FIRMessagingPubSub. + */ +- (instancetype)initWithClient:(FIRMessagingClient *)client NS_DESIGNATED_INITIALIZER; + +/** + * Subscribes an app instance to a topic, enabling it to receive messages + * sent to that topic. + * + * This is an asynchronous call. If subscription fails, FIRMessaging + * invokes the completion callback with the appropriate error. + * + * @see FIRMessagingPubSub unsubscribeWithToken:topic:handler: + * + * @param token The registration token as received from the InstanceID + * library for a given `authorizedEntity` and "gcm" scope. + * @param topic The topic to subscribe to. Should be of the form + * `"/topics/"`. + * @param options Unused parameter, please pass nil or empty dictionary. + * @param handler The callback handler invoked when the subscribe call + * ends. In case of success, a nil error is returned. Otherwise, + * an appropriate error object is returned. + * @discussion This method is thread-safe. However, it is not guaranteed to + * return on the main thread. + */ +- (void)subscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(nullable NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler; + +/** + * Unsubscribes an app instance from a topic, stopping it from receiving + * any further messages sent to that topic. + * + * This is an asynchronous call. If the attempt to unsubscribe fails, + * we invoke the `completion` callback passed in with an appropriate error. + * + * @param token The token used to subscribe to this topic. + * @param topic The topic to unsubscribe from. Should be of the form + * `"/topics/"`. + * @param options Unused parameter, please pass nil or empty dictionary. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + * @discussion This method is thread-safe. However, it is not guaranteed to + * return on the main thread. + */ +- (void)unsubscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(nullable NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler; + +/** + * Asynchronously subscribe to the topic. Adds to the pending list of topic operations. + * Retry in case of failures. This makes a repeated attempt to subscribe to the topic + * as compared to the `subscribe` method above which tries once. + * + * @param topic The topic name to subscribe to. Should be of the form `"/topics/"`. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)subscribeToTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler; + +/** + * Asynchronously unsubscribe from the topic. Adds to the pending list of topic operations. + * Retry in case of failures. This makes a repeated attempt to unsubscribe from the topic + * as compared to the `unsubscribe` method above which tries once. + * + * @param topic The topic name to unsubscribe from. Should be of the form `"/topics/"`. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)unsubscribeFromTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler; + +/** + * Schedule subscriptions sync. + * + * @param immediately YES if the sync should be scheduled immediately else NO if we can delay + * the sync. + */ +- (void)scheduleSync:(BOOL)immediately; + +/** + * Adds the "/topics/" prefix to the topic. + * + * @param topic The topic to add the prefix to. + * + * @return The new topic name with the "/topics/" prefix added. + */ ++ (NSString *)addPrefixToTopic:(NSString *)topic; + +/** + * Removes the "/topics/" prefix from the topic. + * + * @param topic The topic to remove the prefix from. + * + * @return The new topic name with the "/topics/" prefix removed. + */ + ++ (NSString *)removePrefixFromTopic:(NSString *)topic; + +/** + * Check if the topic name has "/topics/" prefix. + * + * @param topic The topic name to verify. + * + * @return YES if the topic name has "/topics/" prefix else NO. + */ ++ (BOOL)hasTopicsPrefix:(NSString *)topic; + +/** + * Check if it's a valid topic name. This includes "/topics/" prefix in the topic name. + * + * @param topic The topic name to verify. + * + * @return YES if the topic name satisfies the regex "/topics/[a-zA-Z0-9-_.~%]{1,900}". + */ ++ (BOOL)isValidTopicWithPrefix:(NSString *)topic; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.m new file mode 100644 index 0000000..0fad4a0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSub.m @@ -0,0 +1,282 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPubSub.h" + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingClient.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPendingTopicsList.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessaging_Private.h" +#import "NSDictionary+FIRMessaging.h" +#import "NSError+FIRMessaging.h" + +static NSString *const kPendingSubscriptionsListKey = + @"com.firebase.messaging.pending-subscriptions"; + +@interface FIRMessagingPubSub () + +@property(nonatomic, readwrite, strong) FIRMessagingPendingTopicsList *pendingTopicUpdates; +@property(nonatomic, readwrite, strong) FIRMessagingClient *client; + +@end + +@implementation FIRMessagingPubSub + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); + // Need this to disable an Xcode warning. + return [self initWithClient:nil]; +} + +- (instancetype)initWithClient:(FIRMessagingClient *)client { + self = [super init]; + if (self) { + _client = client; + [self restorePendingTopicsList]; + } + return self; +} + +- (void)subscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler { + _FIRMessagingDevAssert([token length], @"FIRMessaging error no token specified"); + _FIRMessagingDevAssert([topic length], @"FIRMessaging error Invalid empty topic specified"); + if (!self.client) { + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubFIRMessagingNotSetup]); + return; + } + + token = [token copy]; + topic = [topic copy]; + + if (![options count]) { + options = @{}; + } + + if (![[self class] isValidTopicWithPrefix:topic]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodePubSub000, + @"Invalid FIRMessaging Pubsub topic %@", topic); + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubInvalidTopic]); + return; + } + + if (![self verifyPubSubOptions:options]) { + // we do not want to quit even if options have some invalid values. + FIRMessagingLoggerError(kFIRMessagingMessageCodePubSub001, + @"Invalid options passed to FIRMessagingPubSub with non-string keys or " + "values."); + } + // copy the dictionary would trim non-string keys or values if any. + options = [options fcm_trimNonStringValues]; + + [self.client updateSubscriptionWithToken:token + topic:topic + options:options + shouldDelete:NO + handler:^void(NSError *error) { + handler(error); + }]; +} + +- (void)unsubscribeWithToken:(NSString *)token + topic:(NSString *)topic + options:(NSDictionary *)options + handler:(FIRMessagingTopicOperationCompletion)handler { + _FIRMessagingDevAssert([token length], @"FIRMessaging error no token specified"); + _FIRMessagingDevAssert([topic length], @"FIRMessaging error Invalid empty topic specified"); + + if (!self.client) { + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubFIRMessagingNotSetup]); + return; + } + + token = [token copy]; + topic = [topic copy]; + if (![options count]) { + options = @{}; + } + + if (![[self class] isValidTopicWithPrefix:topic]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodePubSub002, + @"Invalid FIRMessaging Pubsub topic %@", topic); + handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubInvalidTopic]); + return; + } + if (![self verifyPubSubOptions:options]) { + // we do not want to quit even if options have some invalid values. + FIRMessagingLoggerError( + kFIRMessagingMessageCodePubSub003, + @"Invalid options passed to FIRMessagingPubSub with non-string keys or values."); + } + // copy the dictionary would trim non-string keys or values if any. + options = [options fcm_trimNonStringValues]; + + [self.client updateSubscriptionWithToken:token + topic:topic + options:options + shouldDelete:YES + handler:^void(NSError *error) { + handler(error); + }]; +} + +- (void)subscribeToTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler { + [self.pendingTopicUpdates addOperationForTopic:topic + withAction:FIRMessagingTopicActionSubscribe + completion:handler]; +} + +- (void)unsubscribeFromTopic:(NSString *)topic + handler:(nullable FIRMessagingTopicOperationCompletion)handler { + [self.pendingTopicUpdates addOperationForTopic:topic + withAction:FIRMessagingTopicActionUnsubscribe + completion:handler]; +} + +- (void)scheduleSync:(BOOL)immediately { + NSString *fcmToken = [[FIRMessaging messaging] defaultFcmToken]; + if (fcmToken.length) { + [self.pendingTopicUpdates resumeOperationsIfNeeded]; + } +} + +#pragma mark - FIRMessagingPendingTopicsListDelegate + +- (void)pendingTopicsList:(FIRMessagingPendingTopicsList *)list + requestedUpdateForTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + completion:(FIRMessagingTopicOperationCompletion)completion { + + NSString *fcmToken = [[FIRMessaging messaging] defaultFcmToken]; + if (action == FIRMessagingTopicActionSubscribe) { + [self subscribeWithToken:fcmToken topic:topic options:nil handler:completion]; + } else { + [self unsubscribeWithToken:fcmToken topic:topic options:nil handler:completion]; + } +} + +- (void)pendingTopicsListDidUpdate:(FIRMessagingPendingTopicsList *)list { + [self archivePendingTopicsList:list]; +} + +- (BOOL)pendingTopicsListCanRequestTopicUpdates:(FIRMessagingPendingTopicsList *)list { + NSString *fcmToken = [[FIRMessaging messaging] defaultFcmToken]; + return (fcmToken.length > 0); +} + +#pragma mark - Storing Pending Topics + +- (void)archivePendingTopicsList:(FIRMessagingPendingTopicsList *)topicsList { + GULUserDefaults *defaults = [GULUserDefaults standardUserDefaults]; + NSData *pendingData = [NSKeyedArchiver archivedDataWithRootObject:topicsList]; + [defaults setObject:pendingData forKey:kPendingSubscriptionsListKey]; + [defaults synchronize]; +} + +- (void)restorePendingTopicsList { + GULUserDefaults *defaults = [GULUserDefaults standardUserDefaults]; + NSData *pendingData = [defaults objectForKey:kPendingSubscriptionsListKey]; + FIRMessagingPendingTopicsList *subscriptions; + @try { + if (pendingData) { + subscriptions = [NSKeyedUnarchiver unarchiveObjectWithData:pendingData]; + } + } @catch (NSException *exception) { + // Nothing we can do, just continue as if we don't have pending subscriptions + } @finally { + if (subscriptions) { + self.pendingTopicUpdates = subscriptions; + } else { + self.pendingTopicUpdates = [[FIRMessagingPendingTopicsList alloc] init]; + } + self.pendingTopicUpdates.delegate = self; + } +} + +#pragma mark - Private Helpers + +- (BOOL)verifyPubSubOptions:(NSDictionary *)options { + return ![options fcm_hasNonStringKeysOrValues]; +} + +#pragma mark - Topic Name Helpers + +static NSString *const kTopicsPrefix = @"/topics/"; +static NSString *const kTopicRegexPattern = @"/topics/([a-zA-Z0-9-_.~%]+)"; + ++ (NSString *)addPrefixToTopic:(NSString *)topic { + if (![self hasTopicsPrefix:topic]) { + return [NSString stringWithFormat:@"%@%@", kTopicsPrefix, topic]; + } else { + return [topic copy]; + } +} + ++ (NSString *)removePrefixFromTopic:(NSString *)topic { + if ([self hasTopicsPrefix:topic]) { + return [topic substringFromIndex:kTopicsPrefix.length]; + } else { + return [topic copy]; + } +} + ++ (BOOL)hasTopicsPrefix:(NSString *)topic { + return [topic hasPrefix:kTopicsPrefix]; +} + +/** + * Returns a regular expression for matching a topic sender. + * + * @return The topic matching regular expression + */ ++ (NSRegularExpression *)topicRegex { + // Since this is a static regex pattern, we only only need to declare it once. + static NSRegularExpression *topicRegex; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSError *error; + topicRegex = + [NSRegularExpression regularExpressionWithPattern:kTopicRegexPattern + options:NSRegularExpressionAnchorsMatchLines + error:&error]; + }); + return topicRegex; +} + +/** + * Gets the class describing occurences of topic names and sender IDs in the sender. + * + * @param expression The topic expression used to generate a pubsub topic + * + * @return Representation of captured subexpressions in topic regular expression + */ ++ (BOOL)isValidTopicWithPrefix:(NSString *)topic { + NSRange topicRange = NSMakeRange(0, topic.length); + NSRange regexMatchRange = [[self topicRegex] rangeOfFirstMatchInString:topic + options:NSMatchingAnchored + range:topicRange]; + return NSEqualRanges(topicRange, regexMatchRange); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.h new file mode 100644 index 0000000..b51813f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingTopicOperation.h" + +@class FIRMessagingCheckinService; + +@interface FIRMessagingPubSubRegistrar : NSObject + +/** + * Designated Initializer. + * + * @param checkinService The checkin service used to register with Checkin + * server. + * + * @return A new FIRMessagingPubSubRegistrar instance used to subscribe/unsubscribe. + */ +- (instancetype)initWithCheckinService:(FIRMessagingCheckinService *)checkinService; + +/** + * Stops all the subscription requests going on in parallel. This would + * invalidate all the handlers associated with the subscription requests. + */ +- (void)stopAllSubscriptionRequests; + +/** + * Update subscription status for a given topic with FIRMessaging's backend. + * + * @param topic The topic to subscribe to. + * @param token The registration token to be used. + * @param options The options to be passed in during subscription request. + * @param shouldDelete NO if the subscription is being added else YES if being + * removed. + * @param handler The handler invoked once the update subscription request + * finishes. + */ +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.m new file mode 100644 index 0000000..6268302 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingPubSubRegistrar.m @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingPubSubRegistrar.h" + +#import "FIRMessagingCheckinService.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingPubSubRegistrar.h" +#import "FIRMessagingTopicsCommon.h" +#import "NSError+FIRMessaging.h" + +@interface FIRMessagingPubSubRegistrar () + +@property(nonatomic, readwrite, strong) FIRMessagingCheckinService *checkinService; + +@property(nonatomic, readonly, strong) NSOperationQueue *topicOperations; +// Common errors, instantiated, to avoid generating multiple copies +@property(nonatomic, readwrite, strong) NSError *operationInProgressError; + +@end + +@implementation FIRMessagingPubSubRegistrar + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithCheckinService:(FIRMessagingCheckinService *)checkinService { + self = [super init]; + if (self) { + _checkinService = checkinService; + _topicOperations = [[NSOperationQueue alloc] init]; + // Do 10 topic operations at a time; it's enough to keep the TCP connection to the host alive, + // saving hundreds of milliseconds on each request (compared to a serial queue). + _topicOperations.maxConcurrentOperationCount = 10; + } + return self; +} + +- (void)stopAllSubscriptionRequests { + [self.topicOperations cancelAllOperations]; +} + +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler { + + FIRMessagingTopicAction action = FIRMessagingTopicActionSubscribe; + if (shouldDelete) { + action = FIRMessagingTopicActionUnsubscribe; + } + FIRMessagingTopicOperation *operation = + [[FIRMessagingTopicOperation alloc] initWithTopic:topic + action:action + token:token + options:options + checkinService:self.checkinService + completion:handler]; + [self.topicOperations addOperation:operation]; + +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.h new file mode 100644 index 0000000..676c7f1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingDataMessageManager.h" +#import "FIRMessaging.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRMessagingReceiver; +@class GULUserDefaults; +@protocol FIRMessagingReceiverDelegate + +- (void)receiver:(FIRMessagingReceiver *)receiver + receivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage; + +@end + +@interface FIRMessagingReceiver : NSObject + +@property(nonatomic, weak, nullable) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.m new file mode 100644 index 0000000..4d8ec13 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingReceiver.m @@ -0,0 +1,103 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingReceiver.h" + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessaging_Private.h" + +static NSString *const kUpstreamMessageIDUserInfoKey = @"messageID"; +static NSString *const kUpstreamErrorUserInfoKey = @"error"; + +static int downstreamMessageID = 0; + +@interface FIRMessagingReceiver () +@property(nonatomic, strong) GULUserDefaults *defaults; +@end + +@implementation FIRMessagingReceiver + +#pragma mark - FIRMessagingDataMessageManager protocol + +- (void)didReceiveMessage:(NSDictionary *)message withIdentifier:(nullable NSString *)messageID { + if (![messageID length]) { + messageID = [[self class] nextMessageID]; + } + + [self handleDirectChannelMessage:message withIdentifier:messageID]; +} + +- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error { + NSNotification *notification; + if (error) { + NSDictionary *userInfo = @{ + kUpstreamMessageIDUserInfoKey : [messageID copy], + kUpstreamErrorUserInfoKey : error + }; + notification = [NSNotification notificationWithName:FIRMessagingSendErrorNotification + object:nil + userInfo:userInfo]; + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver000, + @"Fail to send upstream message: %@ error: %@", messageID, error); + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver001, @"Will send upstream message: %@", + messageID); + } +} + +- (void)didSendDataMessageWithID:(NSString *)messageID { + // invoke the callbacks asynchronously + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver002, @"Did send upstream message: %@", + messageID); + NSNotification * notification = + [NSNotification notificationWithName:FIRMessagingSendSuccessNotification + object:nil + userInfo:@{ kUpstreamMessageIDUserInfoKey : [messageID copy] }]; + + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; +} + +- (void)didDeleteMessagesOnServer { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver003, + @"Will send deleted messages notification"); + NSNotification * notification = + [NSNotification notificationWithName:FIRMessagingMessagesDeletedNotification + object:nil]; + + [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP]; +} + +#pragma mark - Private Helpers +- (void)handleDirectChannelMessage:(NSDictionary *)message withIdentifier:(NSString *)messageID { + FIRMessagingRemoteMessage *wrappedMessage = [[FIRMessagingRemoteMessage alloc] init]; + wrappedMessage.appData = [message copy]; + wrappedMessage.messageID = messageID; + [self.delegate receiver:self receivedRemoteMessage:wrappedMessage]; +} + ++ (NSString *)nextMessageID { + @synchronized (self) { + ++downstreamMessageID; + return [NSString stringWithFormat:@"gcm-%d", downstreamMessageID]; + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.h new file mode 100644 index 0000000..065479c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.h @@ -0,0 +1,80 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" +#import "FIRMessagingCheckinService.h" + +@class FIRMessagingCheckinStore; +@class FIRMessagingPubSubRegistrar; + +/** + * Handle the registration process for the client. Fetch checkin information from the Checkin + * service if not cached on the device and then try to register the client with FIRMessaging backend. + */ +@interface FIRMessagingRegistrar : NSObject + +@property(nonatomic, readonly, strong) FIRMessagingPubSubRegistrar *pubsubRegistrar; +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; + +/** + * Initialize a FIRMessaging Registrar. + * + * @return A FIRMessaging Registrar object. + */ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +#pragma mark - Checkin + +/** + * Try to load checkin info from the disk if not currently loaded into memory. + * + * @return YES if successfully loaded valid checkin info to memory else NO. + */ +- (BOOL)tryToLoadValidCheckinInfo; + +#pragma mark - Subscribe/Unsubscribe + +/** + * Update the subscription for a given topic for the client. + * + * @param topic The topic for which the subscription should be updated. + * @param token The registration token to be used by the client. + * @param options The extra options if any being passed as part of + * subscription request. + * @param shouldDelete YES if we want to delete an existing subscription else NO + * if we want to create a new subscription. + * @param handler The handler to invoke once the subscription request is + * complete. + */ +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler; + +/** + * Cancel all subscription requests as well as any requests to checkin. Note if + * there are subscription requests waiting on checkin to complete those requests + * would be marked as stale and be NO-OP's if they happen in the future. + * + * Also note this is a one time operation, you should only call this if you want + * to immediately stop all requests and deallocate the registrar. After calling + * this once you would no longer be able to use this registrar object. + */ +- (void)cancelAllRequests; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.m new file mode 100644 index 0000000..47a22ec --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRegistrar.m @@ -0,0 +1,108 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRegistrar.h" + +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPubSubRegistrar.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +@interface FIRMessagingRegistrar () + +@property(nonatomic, readwrite, assign) BOOL stopAllSubscriptions; + +@property(nonatomic, readwrite, strong) FIRMessagingCheckinService *checkinService; +@property(nonatomic, readwrite, strong) FIRMessagingPubSubRegistrar *pubsubRegistrar; + +@end + +@implementation FIRMessagingRegistrar + +- (NSString *)deviceAuthID { + return self.checkinService.deviceAuthID; +} + +- (NSString *)secretToken { + return self.checkinService.secretToken; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _checkinService = [[FIRMessagingCheckinService alloc] init]; + // TODO(chliangGoogle): Merge pubsubRegistrar with Registrar as it is hard to track how many + // checkinService instances by separating classes too often. + _pubsubRegistrar = [[FIRMessagingPubSubRegistrar alloc] initWithCheckinService:_checkinService]; + } + return self; +} + +#pragma mark - Checkin + +- (BOOL)tryToLoadValidCheckinInfo { + [self.checkinService tryToLoadPrefetchedCheckinPreferences]; + return [self.checkinService hasValidCheckinInfo]; +} + +#pragma mark - Subscribe/Unsubscribe + +- (void)updateSubscriptionToTopic:(NSString *)topic + withToken:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + handler:(FIRMessagingTopicOperationCompletion)handler { + _FIRMessagingDevAssert(handler, @"Invalid nil handler"); + + if ([self tryToLoadValidCheckinInfo]) { + [self doUpdateSubscriptionForTopic:topic + token:token + options:options + shouldDelete:shouldDelete + completion:handler]; + + } else { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRegistrar000, + @"Device check in error, no auth credentials found"); + NSError *error = [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeMissingDeviceID]; + handler(error); + } +} + +- (void)cancelAllRequests { + self.stopAllSubscriptions = YES; + [self.pubsubRegistrar stopAllSubscriptionRequests]; +} + +#pragma mark - Private + +- (void)doUpdateSubscriptionForTopic:(NSString *)topic + token:(NSString *)token + options:(NSDictionary *)options + shouldDelete:(BOOL)shouldDelete + completion:(FIRMessagingTopicOperationCompletion)completion { + _FIRMessagingDevAssert([self.checkinService hasValidCheckinInfo], + @"No valid checkin info found before subscribe"); + + [self.pubsubRegistrar updateSubscriptionToTopic:topic + withToken:token + options:options + shouldDelete:shouldDelete + handler:completion]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h new file mode 100644 index 0000000..f0010b3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Swizzle remote-notification callbacks to invoke FIRMessaging methods + * before calling original implementations. + */ +@interface FIRMessagingRemoteNotificationsProxy : NSObject + +/** + * Checks the `FirebaseAppDelegateProxyEnabled` key in the App's Info.plist. If the key is + * missing or incorrectly formatted, returns `YES`. + * + * @return YES if the Application Delegate and User Notification Center methods can be swizzled. + * Otherwise, returns NO. + */ ++ (BOOL)canSwizzleMethods; + +/** + * A shared instance of `FIRMessagingRemoteNotificationsProxy` + */ ++ (instancetype)sharedProxy; + +/** + * Swizzles Application Delegate's remote-notification callbacks and User Notification Center + * delegate callback, and invokes the original selectors once done. + */ +- (void)swizzleMethodsIfPossible; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m new file mode 100644 index 0000000..e3a137f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m @@ -0,0 +1,602 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRemoteNotificationsProxy.h" + +#import +#import + +#import "FIRMessagingConstants.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" +#import "FIRMessaging_Private.h" +#import + +static void * UserNotificationObserverContext = &UserNotificationObserverContext; + +static NSString *kUserNotificationWillPresentSelectorString = + @"userNotificationCenter:willPresentNotification:withCompletionHandler:"; +static NSString *kUserNotificationDidReceiveResponseSelectorString = + @"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:"; + +@interface FIRMessagingRemoteNotificationsProxy () + +@property(strong, nonatomic) NSMutableDictionary *originalAppDelegateImps; +@property(strong, nonatomic) NSMutableDictionary *swizzledSelectorsByClass; + +@property(nonatomic) BOOL didSwizzleMethods; + +@property(nonatomic) BOOL hasSwizzledUserNotificationDelegate; +@property(nonatomic) BOOL isObservingUserNotificationDelegateChanges; + +@property(strong, nonatomic) id userNotificationCenter; +@property(strong, nonatomic) id currentUserNotificationCenterDelegate; + +@property(strong, nonatomic) GULAppDelegateInterceptorID appDelegateInterceptorID; + +@end + +@implementation FIRMessagingRemoteNotificationsProxy + ++ (BOOL)canSwizzleMethods { + return [GULAppDelegateSwizzler isAppDelegateProxyEnabled]; +} + ++ (instancetype)sharedProxy { + static FIRMessagingRemoteNotificationsProxy *proxy; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + proxy = [[FIRMessagingRemoteNotificationsProxy alloc] init]; + }); + return proxy; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _originalAppDelegateImps = [[NSMutableDictionary alloc] init]; + _swizzledSelectorsByClass = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)dealloc { + [self unswizzleAllMethods]; + self.swizzledSelectorsByClass = nil; + [self.originalAppDelegateImps removeAllObjects]; + self.originalAppDelegateImps = nil; + [self removeUserNotificationCenterDelegateObserver]; +} + +- (void)swizzleMethodsIfPossible { + // Already swizzled. + if (self.didSwizzleMethods) { + return; + } + + [GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods]; + self.appDelegateInterceptorID = [GULAppDelegateSwizzler registerAppDelegateInterceptor:self]; + + // Add KVO listener on [UNUserNotificationCenter currentNotificationCenter]'s delegate property + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + if (notificationCenterClass) { + // We are linked against iOS 10 SDK or above + id notificationCenter = getNamedPropertyFromObject(notificationCenterClass, + @"currentNotificationCenter", + notificationCenterClass); + if (notificationCenter) { + [self listenForDelegateChangesInUserNotificationCenter:notificationCenter]; + } + } + + self.didSwizzleMethods = YES; +} + +- (void)unswizzleAllMethods { + if (self.appDelegateInterceptorID) { + [GULAppDelegateSwizzler unregisterAppDelegateInterceptorWithID:self.appDelegateInterceptorID]; + } + + for (NSString *className in self.swizzledSelectorsByClass) { + Class klass = NSClassFromString(className); + NSArray *selectorStrings = self.swizzledSelectorsByClass[className]; + for (NSString *selectorString in selectorStrings) { + SEL selector = NSSelectorFromString(selectorString); + [self unswizzleSelector:selector inClass:klass]; + } + } + [self.swizzledSelectorsByClass removeAllObjects]; +} + +- (void)listenForDelegateChangesInUserNotificationCenter:(id)notificationCenter { + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + if (![notificationCenter isKindOfClass:notificationCenterClass]) { + return; + } + id delegate = getNamedPropertyFromObject(notificationCenter, @"delegate", nil); + Protocol *delegateProtocol = NSProtocolFromString(@"UNUserNotificationCenterDelegate"); + if ([delegate conformsToProtocol:delegateProtocol]) { + // Swizzle this object now, if available + [self swizzleUserNotificationCenterDelegate:delegate]; + } + // Add KVO observer for "delegate" keyPath for future changes + [self addDelegateObserverToUserNotificationCenter:notificationCenter]; +} + +#pragma mark - UNNotificationCenter Swizzling + +- (void)swizzleUserNotificationCenterDelegate:(id _Nonnull)delegate { + if (self.currentUserNotificationCenterDelegate == delegate) { + // Via pointer-check, compare if we have already swizzled this item. + return; + } + Protocol *userNotificationCenterProtocol = + NSProtocolFromString(@"UNUserNotificationCenterDelegate"); + if ([delegate conformsToProtocol:userNotificationCenterProtocol]) { + SEL willPresentNotificationSelector = + NSSelectorFromString(kUserNotificationWillPresentSelectorString); + // Swizzle the optional method + // "userNotificationCenter:willPresentNotification:withCompletionHandler:", if it is + // implemented. Do not swizzle otherwise, as an implementation *will* be created, which will + // fool iOS into thinking that this method is implemented, and therefore not send notifications + // to the fallback method in the app delegate + // "application:didReceiveRemoteNotification:fetchCompletionHandler:". + if ([delegate respondsToSelector:willPresentNotificationSelector]) { + [self swizzleSelector:willPresentNotificationSelector + inClass:[delegate class] + withImplementation:(IMP)FCM_swizzle_willPresentNotificationWithHandler + inProtocol:userNotificationCenterProtocol]; + } + SEL didReceiveNotificationResponseSelector = + NSSelectorFromString(kUserNotificationDidReceiveResponseSelectorString); + if ([delegate respondsToSelector:didReceiveNotificationResponseSelector]) { + [self swizzleSelector:didReceiveNotificationResponseSelector + inClass:[delegate class] + withImplementation:(IMP)FCM_swizzle_didReceiveNotificationResponseWithHandler + inProtocol:userNotificationCenterProtocol]; + } + self.currentUserNotificationCenterDelegate = delegate; + self.hasSwizzledUserNotificationDelegate = YES; + } +} + +- (void)unswizzleUserNotificationCenterDelegate:(id _Nonnull)delegate { + if (self.currentUserNotificationCenterDelegate != delegate) { + // We aren't swizzling this delegate, so don't do anything. + return; + } + SEL willPresentNotificationSelector = + NSSelectorFromString(kUserNotificationWillPresentSelectorString); + // Call unswizzle methods, even if the method was not implemented (it will fail gracefully). + [self unswizzleSelector:willPresentNotificationSelector + inClass:[self.currentUserNotificationCenterDelegate class]]; + SEL didReceiveNotificationResponseSelector = + NSSelectorFromString(kUserNotificationDidReceiveResponseSelectorString); + [self unswizzleSelector:didReceiveNotificationResponseSelector + inClass:[self.currentUserNotificationCenterDelegate class]]; + self.currentUserNotificationCenterDelegate = nil; + self.hasSwizzledUserNotificationDelegate = NO; +} + +#pragma mark - KVO for UNUserNotificationCenter + +- (void)addDelegateObserverToUserNotificationCenter:(id)userNotificationCenter { + [self removeUserNotificationCenterDelegateObserver]; + @try { + [userNotificationCenter addObserver:self + forKeyPath:NSStringFromSelector(@selector(delegate)) + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:UserNotificationObserverContext]; + self.userNotificationCenter = userNotificationCenter; + self.isObservingUserNotificationDelegateChanges = YES; + } @catch (NSException *exception) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxy000, + @"Encountered exception trying to add a KVO observer for " + @"UNUserNotificationCenter's 'delegate' property: %@", + exception); + } @finally { + + } +} + +- (void)removeUserNotificationCenterDelegateObserver { + if (!self.userNotificationCenter) { + return; + } + @try { + [self.userNotificationCenter removeObserver:self + forKeyPath:NSStringFromSelector(@selector(delegate)) + context:UserNotificationObserverContext]; + self.userNotificationCenter = nil; + self.isObservingUserNotificationDelegateChanges = NO; + } @catch (NSException *exception) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxy001, + @"Encountered exception trying to remove a KVO observer for " + @"UNUserNotificationCenter's 'delegate' property: %@", + exception); + } @finally { + + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if (context == UserNotificationObserverContext) { + if ([keyPath isEqualToString:NSStringFromSelector(@selector(delegate))]) { + id oldDelegate = change[NSKeyValueChangeOldKey]; + if (oldDelegate && oldDelegate != [NSNull null]) { + [self unswizzleUserNotificationCenterDelegate:oldDelegate]; + } + id newDelegate = change[NSKeyValueChangeNewKey]; + if (newDelegate && newDelegate != [NSNull null]) { + [self swizzleUserNotificationCenterDelegate:newDelegate]; + } + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +#pragma mark - NSProxy methods + +- (void)saveOriginalImplementation:(IMP)imp forSelector:(SEL)selector { + if (imp && selector) { + NSValue *IMPValue = [NSValue valueWithPointer:imp]; + NSString *selectorString = NSStringFromSelector(selector); + self.originalAppDelegateImps[selectorString] = IMPValue; + } +} + +- (IMP)originalImplementationForSelector:(SEL)selector { + NSString *selectorString = NSStringFromSelector(selector); + NSValue *implementation_value = self.originalAppDelegateImps[selectorString]; + if (!implementation_value) { + return nil; + } + + IMP imp; + [implementation_value getValue:&imp]; + return imp; +} + +- (void)trackSwizzledSelector:(SEL)selector ofClass:(Class)klass { + NSString *className = NSStringFromClass(klass); + NSString *selectorString = NSStringFromSelector(selector); + NSArray *selectors = self.swizzledSelectorsByClass[selectorString]; + if (selectors) { + selectors = [selectors arrayByAddingObject:selectorString]; + } else { + selectors = @[selectorString]; + } + self.swizzledSelectorsByClass[className] = selectors; +} + +- (void)removeImplementationForSelector:(SEL)selector { + NSString *selectorString = NSStringFromSelector(selector); + [self.originalAppDelegateImps removeObjectForKey:selectorString]; +} + +- (void)swizzleSelector:(SEL)originalSelector + inClass:(Class)klass + withImplementation:(IMP)swizzledImplementation + inProtocol:(Protocol *)protocol { + Method originalMethod = class_getInstanceMethod(klass, originalSelector); + + if (originalMethod) { + // This class implements this method, so replace the original implementation + // with our new implementation and save the old implementation. + + IMP __original_method_implementation = + method_setImplementation(originalMethod, swizzledImplementation); + + IMP __nonexistant_method_implementation = [self nonExistantMethodImplementationForClass:klass]; + + if (__original_method_implementation && + __original_method_implementation != __nonexistant_method_implementation && + __original_method_implementation != swizzledImplementation) { + [self saveOriginalImplementation:__original_method_implementation + forSelector:originalSelector]; + } + } else { + // The class doesn't have this method, so add our swizzled implementation as the + // original implementation of the original method. + struct objc_method_description method_description = + protocol_getMethodDescription(protocol, originalSelector, NO, YES); + + BOOL methodAdded = class_addMethod(klass, + originalSelector, + swizzledImplementation, + method_description.types); + if (!methodAdded) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxyMethodNotAdded, + @"Could not add method for %@ to class %@", + NSStringFromSelector(originalSelector), + NSStringFromClass(klass)); + } + } + [self trackSwizzledSelector:originalSelector ofClass:klass]; +} + +- (void)unswizzleSelector:(SEL)selector inClass:(Class)klass { + + Method swizzledMethod = class_getInstanceMethod(klass, selector); + if (!swizzledMethod) { + // This class doesn't seem to have this selector as an instance method? Bail out. + return; + } + + IMP original_imp = [self originalImplementationForSelector:selector]; + if (original_imp) { + // Restore the original implementation as the current implementation + method_setImplementation(swizzledMethod, original_imp); + [self removeImplementationForSelector:selector]; + } else { + // This class originally did not have an implementation for this selector. + + // We can't actually remove methods in Objective C 2.0, but we could set + // its method to something non-existent. This should give us the same + // behavior as if the method was not implemented. + // See: http://stackoverflow.com/a/8276527/9849 + + IMP nonExistantMethodImplementation = [self nonExistantMethodImplementationForClass:klass]; + method_setImplementation(swizzledMethod, nonExistantMethodImplementation); + } +} + +#pragma mark - Reflection Helpers + +// This is useful to generate from a stable, "known missing" selector, as the IMP can be compared +// in case we are setting an implementation for a class that was previously "unswizzled" into a +// non-existant implementation. +- (IMP)nonExistantMethodImplementationForClass:(Class)klass { + SEL nonExistantSelector = NSSelectorFromString(@"aNonExistantMethod"); + IMP nonExistantMethodImplementation = class_getMethodImplementation(klass, nonExistantSelector); + return nonExistantMethodImplementation; +} + +// A safe, non-leaky way return a property object by its name +id getNamedPropertyFromObject(id object, NSString *propertyName, Class klass) { + SEL selector = NSSelectorFromString(propertyName); + if (![object respondsToSelector:selector]) { + return nil; + } + if (!klass) { + klass = [NSObject class]; + } + // Suppress clang warning about leaks in performSelector + // The alternative way to perform this is to invoke + // the method as a block (see http://stackoverflow.com/a/20058585), + // but this approach sometimes returns incomplete objects. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id property = [object performSelector:selector]; +#pragma clang diagnostic pop + if (![property isKindOfClass:klass]) { + return nil; + } + return property; +} + +#pragma mark - UIApplicationDelegate + +#if TARGET_OS_IOS +- (void)application:(UIApplication *)application +didReceiveRemoteNotification:(NSDictionary *)userInfo { + [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; +} +#endif // TARGET_OS_IOS + +- (void)application:(UIApplication *)application +didReceiveRemoteNotification:(NSDictionary *)userInfo +fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; +} + +- (void)application:(UIApplication *)application +didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + // Pass the APNSToken along to FIRMessaging (and auto-detect the token type) + [FIRMessaging messaging].APNSToken = deviceToken; +} + +- (void)application:(UIApplication *)application +didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + // Log the fact that we failed to register for remote notifications + FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxyAPNSFailed, + @"Error in " + @"application:didFailToRegisterForRemoteNotificationsWithError: %@", + error.localizedDescription); +} + +#pragma mark - Swizzled Methods + +/** + * Swizzle the notification handler for iOS 10+ devices. + * Signature of original handler is as below: + * - (void)userNotificationCenter:(UNUserNotificationCenter *)center + * willPresentNotification:(UNNotification *)notification + * withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler + * In order to make FCM SDK compile and compatible with iOS SDKs before iOS 10, hide the + * parameter types from the swizzling implementation. + */ +void FCM_swizzle_willPresentNotificationWithHandler( + id self, SEL _cmd, id center, id notification, void (^handler)(NSUInteger)) { + + FIRMessagingRemoteNotificationsProxy *proxy = [FIRMessagingRemoteNotificationsProxy sharedProxy]; + IMP original_imp = [proxy originalImplementationForSelector:_cmd]; + + void (^callOriginalMethodIfAvailable)(void) = ^{ + if (original_imp) { + ((void (*)(id, SEL, id, id, void (^)(NSUInteger)))original_imp)( + self, _cmd, center, notification, handler); + } + return; + }; + + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + Class notificationClass = NSClassFromString(@"UNNotification"); + if (!notificationCenterClass || !notificationClass) { + // Can't find UserNotifications framework. Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + } + + if (!center || ![center isKindOfClass:[notificationCenterClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!notification || ![notification isKindOfClass:[notificationClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!handler) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + // Attempt to access the user info + id notificationUserInfo = userInfoFromNotification(notification); + + if (!notificationUserInfo) { + // Could not access notification.request.content.userInfo. + callOriginalMethodIfAvailable(); + return; + } + + [[FIRMessaging messaging] appDidReceiveMessage:notificationUserInfo]; + // Execute the original implementation. + callOriginalMethodIfAvailable(); +} + +/** + * Swizzle the notification handler for iOS 10+ devices. + * Signature of original handler is as below: + * - (void)userNotificationCenter:(UNUserNotificationCenter *)center + * didReceiveNotificationResponse:(UNNotificationResponse *)response + * withCompletionHandler:(void (^)(void))completionHandler + * In order to make FCM SDK compile and compatible with iOS SDKs before iOS 10, hide the + * parameter types from the swizzling implementation. + */ +void FCM_swizzle_didReceiveNotificationResponseWithHandler( + id self, SEL _cmd, id center, id response, void (^handler)(void)) { + + FIRMessagingRemoteNotificationsProxy *proxy = [FIRMessagingRemoteNotificationsProxy sharedProxy]; + IMP original_imp = [proxy originalImplementationForSelector:_cmd]; + + void (^callOriginalMethodIfAvailable)(void) = ^{ + if (original_imp) { + ((void (*)(id, SEL, id, id, void (^)(void)))original_imp)( + self, _cmd, center, response, handler); + } + return; + }; + + Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter"); + Class responseClass = NSClassFromString(@"UNNotificationResponse"); + if (!center || ![center isKindOfClass:[notificationCenterClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!response || ![response isKindOfClass:[responseClass class]]) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + if (!handler) { + // Invalid parameter type from the original method. + // Do not swizzle, just execute the original method. + callOriginalMethodIfAvailable(); + return; + } + + // Try to access the response.notification property + SEL notificationSelector = NSSelectorFromString(@"notification"); + if (![response respondsToSelector:notificationSelector]) { + // Cannot access the .notification property. + callOriginalMethodIfAvailable(); + return; + } + id notificationClass = NSClassFromString(@"UNNotification"); + id notification = getNamedPropertyFromObject(response, @"notification", notificationClass); + + // With a notification object, use the common code to reach deep into notification + // (notification.request.content.userInfo) + id notificationUserInfo = userInfoFromNotification(notification); + if (!notificationUserInfo) { + // Could not access notification.request.content.userInfo. + callOriginalMethodIfAvailable(); + return; + } + + [[FIRMessaging messaging] appDidReceiveMessage:notificationUserInfo]; + // Execute the original implementation. + callOriginalMethodIfAvailable(); +} + +id userInfoFromNotification(id notification) { + + // Select the userInfo field from UNNotification.request.content.userInfo. + SEL requestSelector = NSSelectorFromString(@"request"); + if (![notification respondsToSelector:requestSelector]) { + // Cannot access the request property. + return nil; + } + Class requestClass = NSClassFromString(@"UNNotificationRequest"); + id notificationRequest = getNamedPropertyFromObject(notification, @"request", requestClass); + + SEL notificationContentSelector = NSSelectorFromString(@"content"); + if (!notificationRequest + || ![notificationRequest respondsToSelector:notificationContentSelector]) { + // Cannot access the content property. + return nil; + } + Class contentClass = NSClassFromString(@"UNNotificationContent"); + id notificationContent = getNamedPropertyFromObject(notificationRequest, + @"content", + contentClass); + + SEL notificationUserInfoSelector = NSSelectorFromString(@"userInfo"); + if (!notificationContent + || ![notificationContent respondsToSelector:notificationUserInfoSelector]) { + // Cannot access the userInfo property. + return nil; + } + id notificationUserInfo = getNamedPropertyFromObject(notificationContent, + @"userInfo", + [NSDictionary class]); + + if (!notificationUserInfo) { + // This is not the expected notification handler. + return nil; + } + + return notificationUserInfo; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.h new file mode 100644 index 0000000..09f1d44 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.h @@ -0,0 +1,201 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRMessagingPersistentSyncMessage; + +// table data handlers +/** + * Handle message stored in the outgoing RMQ messages table. + * + * @param rmqId The rmqID of the message. + * @param tag The message tag. + * @param data The data stored in the message. + */ +typedef void(^FCMOutgoingRmqMessagesTableHandler)(int64_t rmqId, int8_t tag, NSData *data); + +/// Outgoing messages RMQ table +extern NSString *const kTableOutgoingRmqMessages; +/// Server to device RMQ table +extern NSString *const kTableS2DRmqIds; + +@interface FIRMessagingRmq2PersistentStore : NSObject + +/** + * Initialize and open the RMQ database on the client. + * + * @param databaseName The name for RMQ database. + * + * @return A store used to persist messages on the client. + */ +- (instancetype)initWithDatabaseName:(NSString *)databaseName; + +/** + * Save outgoing message in RMQ. + * + * @param rmqId The rmqID for the message. + * @param tag The tag of the message proto. + * @param data The data being sent in the message. + * @param error The error if any while saving the message to the persistent store. + * + * @return YES if the message was successfully saved to the persistent store else NO. + */ +- (BOOL)saveMessageWithRmqId:(int64_t)rmqId + tag:(int8_t)tag + data:(NSData *)data + error:(NSError **)error; + +/** + * Add unacked server to device message with a given rmqID to the persistent store. + * + * @param rmqId The rmqID of the message that was not acked by the cient. + * + * @return YES if the save was successful else NO. + */ +- (BOOL)saveUnackedS2dMessageWithRmqId:(NSString *)rmqId; + +/** + * Update the last RMQ ID that was sent by the client. + * + * @param rmqID The latest rmqID sent by the device. + * + * @return YES if the last rmqID was successfully saved else NO. + */ +- (BOOL)updateLastOutgoingRmqId:(int64_t)rmqID; + +#pragma mark - Query + +/** + * Query the highest rmqID saved in the Outgoing messages table. + * + * @return The highest rmqID amongst all the messages in the Outgoing RMQ table. If no message + * was ever persisted return 0. + */ +- (int64_t)queryHighestRmqId; + +/** + * The last rmqID that was saved on the client. + * + * @return The last rmqID that was saved. If no rmqID was ever persisted return 0. + */ +- (int64_t)queryLastRmqId; + +/** + * Get a list of all unacked server to device messages stored on the client. + * + * @return List of all unacked s2d messages in the persistent store. + */ +- (NSArray *)unackedS2dRmqIds; + +/** + * Iterate over all outgoing messages in the RMQ table. + * + * @param handler The handler invoked with each message in the outgoing RMQ table. + */ +- (void)scanOutgoingRmqMessagesWithHandler:(FCMOutgoingRmqMessagesTableHandler)handler; + +#pragma mark - Delete + +/** + * Delete messages with given rmqID's from a table. + * + * @param tableName The table name from which to delete the rmq messages. + * @param rmqIds The rmqID's of the messages to be deleted. + * + * @return The number of messages that were successfully deleted. + */ +- (int)deleteMessagesFromTable:(NSString *)tableName + withRmqIds:(NSArray *)rmqIds; + +/** + * Remove database from the device. + * + * @param dbName The database name to be deleted. + */ ++ (void)removeDatabase:(NSString *)dbName; + +#pragma mark - Sync Messages + +/** + * Save sync message to persistent store to check for duplicates. + * + * @param rmqID The rmqID of the message to save. + * @param expirationTime The expiration time of the message to save. + * @param apnsReceived YES if the message was received via APNS else NO. + * @param mcsReceived YES if the message was received via MCS else NO. + * @param error The error if any while saving the message to store. + * + * @return YES if the message was saved successfully else NO. + */ +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError **)error; + +/** + * Update sync message received via APNS. + * + * @param rmqID The rmqID of the sync message. + * @param error The error if any while updating the sync message in persistence. + * + * @return YES if the update was successful else NO. + */ +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID + error:(NSError **)error; + +/** + * Update sync message received via MCS. + * + * @param rmqID The rmqID of the sync message. + * @param error The error if any while updating the sync message in persistence. + * + * @return YES if the update was successful else NO. + */ +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID + error:(NSError **)error; + +/** + * Query sync message table for a given rmqID. + * + * @param rmqID The rmqID to search for in SYNC_RMQ. + * + * @return The sync message that was persisted with `rmqID`. If no such message was persisted + * return nil. + */ +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete sync message with rmqID. + * + * @param rmqID The rmqID of the message to delete. + * + * @return YES if a sync message with rmqID was found and deleted successfully else NO. + */ +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete the expired sync messages from persisten store. Also deletes messages that have been + * delivered both via APNS and MCS. + * + * @param error The error if any while deleting the messages. + * + * @return The total number of messages that were deleted from the persistent store. + */ +- (int)deleteExpiredOrFinishedSyncMessages:(NSError **)error; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.m new file mode 100644 index 0000000..bef6aac --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmq2PersistentStore.m @@ -0,0 +1,811 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRmq2PersistentStore.h" + +#import + +#import "FIRMessagingConstants.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPersistentSyncMessage.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" +#import "Protos/GtalkCore.pbobjc.h" + +#ifndef _FIRMessagingRmqLogAndExit +#define _FIRMessagingRmqLogAndExit(stmt, return_value) \ +do { \ +[self logErrorAndFinalizeStatement:stmt]; \ +return return_value; \ +} while(0) +#endif + +typedef enum : NSUInteger { + FIRMessagingRmqDirectoryUnknown, + FIRMessagingRmqDirectoryDocuments, + FIRMessagingRmqDirectoryApplicationSupport, +} FIRMessagingRmqDirectory; + +static NSString *const kFCMRmqStoreTag = @"FIRMessagingRmqStore:"; + +// table names +NSString *const kTableOutgoingRmqMessages = @"outgoingRmqMessages"; +NSString *const kTableLastRmqId = @"lastrmqid"; +NSString *const kOldTableS2DRmqIds = @"s2dRmqIds"; +NSString *const kTableS2DRmqIds = @"s2dRmqIds_1"; + +// Used to prevent de-duping of sync messages received both via APNS and MCS. +NSString *const kTableSyncMessages = @"incomingSyncMessages"; + +static NSString *const kTablePrefix = @""; + +// create tables +static NSString *const kCreateTableOutgoingRmqMessages = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id INTEGER, " + @"type INTEGER, " + @"ts INTEGER, " + @"data BLOB)"; + +static NSString *const kCreateTableLastRmqId = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id INTEGER)"; + +static NSString *const kCreateTableS2DRmqIds = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id TEXT)"; + +static NSString *const kCreateTableSyncMessages = + @"create TABLE IF NOT EXISTS %@%@ " + @"(_id INTEGER PRIMARY KEY, " + @"rmq_id TEXT, " + @"expiration_ts INTEGER, " + @"apns_recv INTEGER, " + @"mcs_recv INTEGER)"; + +static NSString *const kDropTableCommand = + @"drop TABLE if exists %@%@"; + +// table infos +static NSString *const kRmqIdColumn = @"rmq_id"; +static NSString *const kDataColumn = @"data"; +static NSString *const kProtobufTagColumn = @"type"; +static NSString *const kIdColumn = @"_id"; + +static NSString *const kOutgoingRmqMessagesColumns = @"rmq_id, type, data"; + +// Sync message columns +static NSString *const kSyncMessagesColumns = @"rmq_id, expiration_ts, apns_recv, mcs_recv"; +// Message time expiration in seconds since 1970 +static NSString *const kSyncMessageExpirationTimestampColumn = @"expiration_ts"; +static NSString *const kSyncMessageAPNSReceivedColumn = @"apns_recv"; +static NSString *const kSyncMessageMCSReceivedColumn = @"mcs_recv"; + +// table data handlers +typedef void(^FCMOutgoingRmqMessagesTableHandler)(int64_t rmqId, int8_t tag, NSData *data); + +// Utility to create an NSString from a sqlite3 result code +NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + const char *errorStr = sqlite3_errstr(result); +#pragma pop + NSString *errorString = [NSString stringWithFormat:@"%d - %s", result, errorStr]; + return errorString; +} + +@interface FIRMessagingRmq2PersistentStore () { + sqlite3 *_database; +} + +@property(nonatomic, readwrite, strong) NSString *databaseName; +@property(nonatomic, readwrite, assign) FIRMessagingRmqDirectory currentDirectory; + +@end + +@implementation FIRMessagingRmq2PersistentStore + +- (instancetype)initWithDatabaseName:(NSString *)databaseName { + self = [super init]; + if (self) { + _databaseName = [databaseName copy]; +#if TARGET_OS_IOS + BOOL didMoveToApplicationSupport = + [self moveToApplicationSupportSubDirectory:kFIRMessagingSubDirectoryName]; + + _currentDirectory = didMoveToApplicationSupport + ? FIRMessagingRmqDirectoryApplicationSupport + : FIRMessagingRmqDirectoryDocuments; +#else + _currentDirectory = FIRMessagingRmqDirectoryApplicationSupport; +#endif + + [self openDatabase:_databaseName]; + } + return self; +} + +- (void)dealloc { + sqlite3_close(_database); +} + +- (BOOL)moveToApplicationSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), + NSUserDomainMask, YES); + NSString *applicationSupportDirPath = directoryPaths.lastObject; + NSArray *components = @[applicationSupportDirPath, subDirectoryName]; + NSString *subDirectoryPath = [NSString pathWithComponents:components]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + // Cannot move to non-existent directory + return NO; + } + + if ([self doesFileExistInDirectory:FIRMessagingRmqDirectoryDocuments]) { + NSString *oldPlistPath = [[self class] pathForDatabase:self.databaseName + inDirectory:FIRMessagingRmqDirectoryDocuments]; + NSString *newPlistPath = [[self class] + pathForDatabase:self.databaseName + inDirectory:FIRMessagingRmqDirectoryApplicationSupport]; + + if ([self doesFileExistInDirectory:FIRMessagingRmqDirectoryApplicationSupport]) { + // File exists in both Documents and ApplicationSupport, delete the one in Documents + NSError *deleteError; + if (![[NSFileManager defaultManager] removeItemAtPath:oldPlistPath error:&deleteError]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore000, + @"Failed to delete old copy of %@.sqlite in Documents %@", + self.databaseName, deleteError); + } + return NO; + } + NSError *moveError; + if (![[NSFileManager defaultManager] moveItemAtPath:oldPlistPath + toPath:newPlistPath + error:&moveError]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore001, + @"Failed to move file %@ from %@ to %@. Error: %@", self.databaseName, + oldPlistPath, newPlistPath, moveError); + return NO; + } + } + // We moved the file if it existed, otherwise we didn't need to do anything + return YES; +} + +- (BOOL)doesFileExistInDirectory:(FIRMessagingRmqDirectory)directory { + NSString *path = [[self class] pathForDatabase:self.databaseName inDirectory:directory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + ++ (NSString *)pathForDatabase:(NSString *)dbName inDirectory:(FIRMessagingRmqDirectory)directory { + NSArray *paths; + NSArray *components; + NSString *dbNameWithExtension = [NSString stringWithFormat:@"%@.sqlite", dbName]; + NSString *errorMessage; + + switch (directory) { + case FIRMessagingRmqDirectoryDocuments: + paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + components = @[paths.lastObject, dbNameWithExtension]; + break; + + case FIRMessagingRmqDirectoryApplicationSupport: + paths = NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), + NSUserDomainMask, + YES); + components = @[ + paths.lastObject, + kFIRMessagingSubDirectoryName, + dbNameWithExtension + ]; + break; + + default: + errorMessage = [NSString stringWithFormat:@"Invalid directory type %lu", + (unsigned long)directory]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreInvalidRmqDirectory, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + break; + } + + return [NSString pathWithComponents:components]; +} + +- (void)createTableWithName:(NSString *)tableName command:(NSString *)command { + char *error; + NSString *createDatabase = [NSString stringWithFormat:command, kTablePrefix, tableName]; + if (sqlite3_exec(_database, [createDatabase UTF8String], NULL, NULL, &error) != SQLITE_OK) { + // remove db before failing + [self removeDatabase]; + NSString *errorMessage = [NSString stringWithFormat:@"Couldn't create table: %@ %@", + kCreateTableOutgoingRmqMessages, + [NSString stringWithCString:error encoding:NSUTF8StringEncoding]]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingTable, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + } +} + +- (void)dropTableWithName:(NSString *)tableName { + char *error; + NSString *dropTableSQL = [NSString stringWithFormat:kDropTableCommand, kTablePrefix, tableName]; + if (sqlite3_exec(_database, [dropTableSQL UTF8String], NULL, NULL, &error) != SQLITE_OK) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore002, + @"Failed to remove table %@", tableName); + } +} + +- (void)removeDatabase { + NSString *path = [[self class] pathForDatabase:self.databaseName + inDirectory:self.currentDirectory]; + [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; +} + ++ (void)removeDatabase:(NSString *)dbName { + NSString *documentsDirPath = [self pathForDatabase:dbName + inDirectory:FIRMessagingRmqDirectoryDocuments]; + NSString *standardDirPath = + [self pathForDatabase:dbName inDirectory:FIRMessagingRmqDirectoryApplicationSupport]; + [[NSFileManager defaultManager] removeItemAtPath:documentsDirPath error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:standardDirPath error:nil]; +} + +- (void)openDatabase:(NSString *)dbName { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *path = [[self class] pathForDatabase:dbName inDirectory:self.currentDirectory]; + + BOOL didOpenDatabase = YES; + if (![fileManager fileExistsAtPath:path]) { + // We've to separate between different versions here because of backwards compatbility issues. + int result = sqlite3_open([path UTF8String], &_database); + if (result != SQLITE_OK) { + NSString *errorString = FIRMessagingStringFromSQLiteResult(result); + NSString *errorMessage = + [NSString stringWithFormat:@"Could not open existing RMQ database at path %@, error: %@", + path, + errorString]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + return; + } + [self createTableWithName:kTableOutgoingRmqMessages + command:kCreateTableOutgoingRmqMessages]; + + [self createTableWithName:kTableLastRmqId command:kCreateTableLastRmqId]; + [self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds]; + } else { + // Calling sqlite3_open should create the database, since the file doesn't exist. + int result = sqlite3_open([path UTF8String], &_database); + if (result != SQLITE_OK) { + NSString *errorString = FIRMessagingStringFromSQLiteResult(result); + NSString *errorMessage = + [NSString stringWithFormat:@"Could not create RMQ database at path %@, error: %@", + path, + errorString]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingDatabase, + @"%@", + errorMessage); + NSAssert(NO, errorMessage); + didOpenDatabase = NO; + } else { + [self updateDbWithStringRmqID]; + } + } + + if (didOpenDatabase) { + [self createTableWithName:kTableSyncMessages command:kCreateTableSyncMessages]; + } +} + +- (void)updateDbWithStringRmqID { + [self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds]; + [self dropTableWithName:kOldTableS2DRmqIds]; +} + +#pragma mark - Insert + +- (BOOL)saveUnackedS2dMessageWithRmqId:(NSString *)rmqId { + NSString *insertFormat = @"INSERT INTO %@ (%@) VALUES (?)"; + NSString *insertSQL = [NSString stringWithFormat:insertFormat, + kTableS2DRmqIds, + kRmqIdColumn]; + sqlite3_stmt *insert_statement; + if (sqlite3_prepare_v2(_database, [insertSQL UTF8String], -1, &insert_statement, NULL) + != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_text(insert_statement, + 1, + [rmqId UTF8String], + (int)[rmqId length], + SQLITE_STATIC) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_step(insert_statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + sqlite3_finalize(insert_statement); + return YES; +} + +- (BOOL)saveMessageWithRmqId:(int64_t)rmqId + tag:(int8_t)tag + data:(NSData *)data + error:(NSError **)error { + NSString *insertFormat = @"INSERT INTO %@ (%@, %@, %@) VALUES (?, ?, ?)"; + NSString *insertSQL = [NSString stringWithFormat:insertFormat, + kTableOutgoingRmqMessages, // table + kRmqIdColumn, kProtobufTagColumn, kDataColumn /* columns */]; + sqlite3_stmt *insert_statement; + if (sqlite3_prepare_v2(_database, [insertSQL UTF8String], -1, &insert_statement, NULL) + != SQLITE_OK) { + if (error) { + *error = [NSError errorWithDomain:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_database)] + code:sqlite3_errcode(_database) + userInfo:nil]; + } + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_int64(insert_statement, 1, rmqId) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_int(insert_statement, 2, tag) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_bind_blob(insert_statement, 3, [data bytes], (int)[data length], NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + if (sqlite3_step(insert_statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(insert_statement, NO); + } + + sqlite3_finalize(insert_statement); + return YES; +} + +- (int)deleteMessagesFromTable:(NSString *)tableName + withRmqIds:(NSArray *)rmqIds { + _FIRMessagingDevAssert([tableName isEqualToString:kTableOutgoingRmqMessages] || + [tableName isEqualToString:kTableLastRmqId] || + [tableName isEqualToString:kTableS2DRmqIds] || + [tableName isEqualToString:kTableSyncMessages], + @"%@: Invalid Table Name %@", kFCMRmqStoreTag, tableName); + + BOOL isRmqIDString = NO; + // RmqID is a string only for outgoing messages + if ([tableName isEqualToString:kTableS2DRmqIds] || + [tableName isEqualToString:kTableSyncMessages]) { + isRmqIDString = YES; + } + + NSMutableString *delete = [NSMutableString stringWithFormat:@"DELETE FROM %@ WHERE ", tableName]; + + NSString *toDeleteArgument = [NSString stringWithFormat:@"%@ = ? OR ", kRmqIdColumn]; + + int toDelete = (int)[rmqIds count]; + if (toDelete == 0) { + return 0; + } + int maxBatchSize = 100; + int start = 0; + int deleteCount = 0; + while (start < toDelete) { + + // construct the WHERE argument + int end = MIN(start + maxBatchSize, toDelete); + NSMutableString *whereArgument = [NSMutableString string]; + for (int i = start; i < end; i++) { + [whereArgument appendString:toDeleteArgument]; + } + // remove the last * OR * from argument + NSRange range = NSMakeRange([whereArgument length] -4, 4); + [whereArgument deleteCharactersInRange:range]; + NSString *deleteQuery = [NSString stringWithFormat:@"%@ %@", delete, whereArgument]; + + + // sqlite update + sqlite3_stmt *delete_statement; + if (sqlite3_prepare_v2(_database, [deleteQuery UTF8String], + -1, &delete_statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(delete_statement, 0); + } + + // bind values + int rmqIndex = 0; + int placeholderIndex = 1; // placeholders in sqlite3 start with 1 + for (NSString *rmqId in rmqIds) { // objectAtIndex: is O(n) -- would make it slow + if (rmqIndex < start) { + rmqIndex++; + continue; + } else if (rmqIndex >= end) { + break; + } else { + if (isRmqIDString) { + if (sqlite3_bind_text(delete_statement, + placeholderIndex, + [rmqId UTF8String], + (int)[rmqId length], + SQLITE_STATIC) != SQLITE_OK) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore003, + @"Failed to bind rmqID %@", rmqId); + continue; + } + } else { + int64_t rmqIdValue = [rmqId longLongValue]; + sqlite3_bind_int64(delete_statement, placeholderIndex, rmqIdValue); + } + placeholderIndex++; + } + rmqIndex++; + } + if (sqlite3_step(delete_statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(delete_statement, deleteCount); + } + sqlite3_finalize(delete_statement); + deleteCount += sqlite3_changes(_database); + start = end; + } + + // if we are here all of our sqlite queries should have succeeded + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore004, + @"%@ Trying to delete %d s2D ID's, successfully deleted %d", + kFCMRmqStoreTag, toDelete, deleteCount); + return deleteCount; +} + +#pragma mark - Query + +- (int64_t)queryHighestRmqId { + NSString *queryFormat = @"SELECT %@ FROM %@ ORDER BY %@ DESC LIMIT %d"; + NSString *query = [NSString stringWithFormat:queryFormat, + kRmqIdColumn, // column + kTableOutgoingRmqMessages, // table + kRmqIdColumn, // order by column + 1]; // limit + + sqlite3_stmt *statement; + int64_t highestRmqId = 0; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, highestRmqId); + } + if (sqlite3_step(statement) == SQLITE_ROW) { + highestRmqId = sqlite3_column_int64(statement, 0); + } + sqlite3_finalize(statement); + return highestRmqId; +} + +- (int64_t)queryLastRmqId { + NSString *queryFormat = @"SELECT %@ FROM %@ ORDER BY %@ DESC LIMIT %d"; + NSString *query = [NSString stringWithFormat:queryFormat, + kRmqIdColumn, // column + kTableLastRmqId, // table + kRmqIdColumn, // order by column + 1]; // limit + + sqlite3_stmt *statement; + int64_t lastRmqId = 0; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, lastRmqId); + } + if (sqlite3_step(statement) == SQLITE_ROW) { + lastRmqId = sqlite3_column_int64(statement, 0); + } + sqlite3_finalize(statement); + return lastRmqId; +} + +- (BOOL)updateLastOutgoingRmqId:(int64_t)rmqID { + NSString *queryFormat = @"INSERT OR REPLACE INTO %@ (%@, %@) VALUES (?, ?)"; + NSString *query = [NSString stringWithFormat:queryFormat, + kTableLastRmqId, // table + kIdColumn, kRmqIdColumn]; // columns + sqlite3_stmt *statement; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + if (sqlite3_bind_int(statement, 1, 1) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + if (sqlite3_bind_int64(statement, 2, rmqID) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + if (sqlite3_step(statement) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(statement, NO); + } + sqlite3_finalize(statement); + return YES; +} + +- (NSArray *)unackedS2dRmqIds { + NSString *queryFormat = @"SELECT %@ FROM %@ ORDER BY %@ ASC"; + NSString *query = [NSString stringWithFormat:queryFormat, + kRmqIdColumn, + kTableS2DRmqIds, + kRmqIdColumn]; + sqlite3_stmt *statement; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore005, + @"%@: Could not find s2d ids", kFCMRmqStoreTag); + _FIRMessagingRmqLogAndExit(statement, @[]); + } + NSMutableArray *rmqIDArray = [NSMutableArray array]; + while (sqlite3_step(statement) == SQLITE_ROW) { + const char *rmqID = (char *)sqlite3_column_text(statement, 0); + [rmqIDArray addObject:[NSString stringWithUTF8String:rmqID]]; + } + sqlite3_finalize(statement); + return rmqIDArray; +} + +#pragma mark - Scan + +- (void)scanOutgoingRmqMessagesWithHandler:(FCMOutgoingRmqMessagesTableHandler)handler { + static NSString *queryFormat = @"SELECT %@ FROM %@ WHERE %@ != 0 ORDER BY %@ ASC"; + NSString *query = [NSString stringWithFormat:queryFormat, + kOutgoingRmqMessagesColumns, // select (rmq_id, type, data) + kTableOutgoingRmqMessages, // from table + kRmqIdColumn, // where + kRmqIdColumn]; // order by + sqlite3_stmt *statement; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) { + [self logError]; + sqlite3_finalize(statement); + return; + } + // can query sqlite3 for this but this is fine + const int rmqIdColumnNumber = 0; + const int typeColumnNumber = 1; + const int dataColumnNumber = 2; + while (sqlite3_step(statement) == SQLITE_ROW) { + int64_t rmqId = sqlite3_column_int64(statement, rmqIdColumnNumber); + int8_t type = sqlite3_column_int(statement, typeColumnNumber); + const void *bytes = sqlite3_column_blob(statement, dataColumnNumber); + int length = sqlite3_column_bytes(statement, dataColumnNumber); + _FIRMessagingDevAssert(bytes != NULL, + @"%@ Message with no data being stored in Rmq", + kFCMRmqStoreTag); + NSData *data = [NSData dataWithBytes:bytes length:length]; + handler(rmqId, type, data); + } + sqlite3_finalize(statement); +} + +#pragma mark - Sync Messages + +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID { + _FIRMessagingDevAssert([rmqID length], @"Invalid rmqID key %@ to search in SYNC_RMQ", rmqID); + + NSString *queryFormat = @"SELECT %@ FROM %@ WHERE %@ = '%@'"; + NSString *query = [NSString stringWithFormat:queryFormat, + kSyncMessagesColumns, // SELECT (rmq_id, expiration_ts, apns_recv, mcs_recv) + kTableSyncMessages, // FROM sync_rmq + kRmqIdColumn, // WHERE rmq_id + rmqID]; + + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + [self logError]; + sqlite3_finalize(stmt); + return nil; + } + + const int rmqIDColumn = 0; + const int expirationTimestampColumn = 1; + const int apnsReceivedColumn = 2; + const int mcsReceivedColumn = 3; + + int count = 0; + FIRMessagingPersistentSyncMessage *persistentMessage; + + while (sqlite3_step(stmt) == SQLITE_ROW) { + NSString *rmqID = + [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, rmqIDColumn)]; + int64_t expirationTimestamp = sqlite3_column_int64(stmt, expirationTimestampColumn); + BOOL apnsReceived = sqlite3_column_int(stmt, apnsReceivedColumn); + BOOL mcsReceived = sqlite3_column_int(stmt, mcsReceivedColumn); + + // create a new persistent message + persistentMessage = + [[FIRMessagingPersistentSyncMessage alloc] initWithRMQID:rmqID expirationTime:expirationTimestamp]; + persistentMessage.apnsReceived = apnsReceived; + persistentMessage.mcsReceived = mcsReceived; + + count++; + } + sqlite3_finalize(stmt); + + _FIRMessagingDevAssert(count <= 1, @"Found multiple messages in %@ with same RMQ ID", kTableSyncMessages); + return persistentMessage; +} + +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID { + _FIRMessagingDevAssert([rmqID length], @"Invalid rmqID key %@ to delete in SYNC_RMQ", rmqID); + return [self deleteMessagesFromTable:kTableSyncMessages withRmqIds:@[rmqID]] > 0; +} + +- (int)deleteExpiredOrFinishedSyncMessages:(NSError *__autoreleasing *)error { + int64_t now = FIRMessagingCurrentTimestampInSeconds(); + NSString *deleteSQL = @"DELETE FROM %@ " + @"WHERE %@ < %lld OR " // expirationTime < now + @"(%@ = 1 AND %@ = 1)"; // apns_received = 1 AND mcs_received = 1 + NSString *query = [NSString stringWithFormat:deleteSQL, + kTableSyncMessages, + kSyncMessageExpirationTimestampColumn, + now, + kSyncMessageAPNSReceivedColumn, + kSyncMessageMCSReceivedColumn]; + + NSString *errorReason = @"Failed to save delete expired sync messages from store."; + + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : errorReason }]; + } + _FIRMessagingRmqLogAndExit(stmt, 0); + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : errorReason }]; + } + _FIRMessagingRmqLogAndExit(stmt, 0); + } + + sqlite3_finalize(stmt); + int deleteCount = sqlite3_changes(_database); + return deleteCount; +} + +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError **)error { + _FIRMessagingDevAssert([rmqID length], @"Invalid nil message to persist to SYNC_RMQ"); + + NSString *insertFormat = @"INSERT INTO %@ (%@, %@, %@, %@) VALUES (?, ?, ?, ?)"; + NSString *insertSQL = [NSString stringWithFormat:insertFormat, + kTableSyncMessages, // Table name + kRmqIdColumn, // rmq_id + kSyncMessageExpirationTimestampColumn, // expiration_ts + kSyncMessageAPNSReceivedColumn, // apns_recv + kSyncMessageMCSReceivedColumn /* mcs_recv */]; + + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(_database, [insertSQL UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : @"Failed to save sync message to store." }]; + } + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_text(stmt, 1, [rmqID UTF8String], (int)[rmqID length], NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_int64(stmt, 2, expirationTime) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_int(stmt, 3, apnsReceived ? 1 : 0) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_int(stmt, 4, mcsReceived ? 1 : 0) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + sqlite3_finalize(stmt); + return YES; +} + +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID + error:(NSError **)error { + return [self updateSyncMessageWithRmqID:rmqID + column:kSyncMessageAPNSReceivedColumn + value:YES + error:error]; +} + +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID + error:(NSError *__autoreleasing *)error { + return [self updateSyncMessageWithRmqID:rmqID + column:kSyncMessageMCSReceivedColumn + value:YES + error:error]; +} + +- (BOOL)updateSyncMessageWithRmqID:(NSString *)rmqID + column:(NSString *)column + value:(BOOL)value + error:(NSError **)error { + _FIRMessagingDevAssert([column isEqualToString:kSyncMessageAPNSReceivedColumn] || + [column isEqualToString:kSyncMessageMCSReceivedColumn], + @"Invalid column name %@ for SYNC_RMQ", column); + NSString *queryFormat = @"UPDATE %@ " // Table name + @"SET %@ = %d " // column=value + @"WHERE %@ = ?"; // condition + NSString *query = [NSString stringWithFormat:queryFormat, + kTableSyncMessages, + column, + value ? 1 : 0, + kRmqIdColumn]; + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) { + if (error) { + *error = [NSError fcm_errorWithCode:sqlite3_errcode(_database) + userInfo:@{ @"error" : @"Failed to update sync message"}]; + } + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_bind_text(stmt, 1, [rmqID UTF8String], (int)[rmqID length], NULL) != SQLITE_OK) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + _FIRMessagingRmqLogAndExit(stmt, NO); + } + + sqlite3_finalize(stmt); + return YES; + +} + +#pragma mark - Private + +- (NSString *)lastErrorMessage { + return [NSString stringWithFormat:@"%s", sqlite3_errmsg(_database)]; +} + +- (int)lastErrorCode { + return sqlite3_errcode(_database); +} + +- (void)logError { + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore006, + @"%@ error: code (%d) message: %@", kFCMRmqStoreTag, [self lastErrorCode], + [self lastErrorMessage]); +} + +- (void)logErrorAndFinalizeStatement:(sqlite3_stmt *)stmt { + [self logError]; + sqlite3_finalize(stmt); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.h new file mode 100644 index 0000000..ba48b98 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.h @@ -0,0 +1,190 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GtalkDataMessageStanza; +@class GPBMessage; + +@class FIRMessagingPersistentSyncMessage; + +/** + * Called on each raw message. + */ +typedef void(^FIRMessagingRmqMessageHandler)(int64_t rmqId, int8_t tag, NSData *data); + +/** + * Called on each DataMessageStanza. + */ +typedef void(^FIRMessagingDataMessageHandler)(int64_t rmqId, GtalkDataMessageStanza *stanza); + +/** + * Used to scan through the rmq and perform actions on messages as required. + */ +@protocol FIRMessagingRmqScanner + +/** + * Scan the RMQ for outgoing messages and process them as required. + */ +- (void)scanWithRmqMessageHandler:(FIRMessagingRmqMessageHandler)rmqMessageHandler + dataMessageHandler:(FIRMessagingDataMessageHandler)dataMessageHandler; + +@end + +/** + * This manages the RMQ persistent store. + * + * The store is used to store all the S2D id's that were received by the client and were ACK'ed + * by us but the server hasn't confirmed the ACK. We don't delete these id's until the server + * ACK's us that they have received them. + * + * We also store the upstream messages(d2s) that were sent by the client. + * + * Also store the lastRMQId that was sent by us so that for a new connection being setup we don't + * duplicate RMQ Id's for the new messages. + */ +@interface FIRMessagingRmqManager : NSObject + +// designated initializer +- (instancetype)initWithDatabaseName:(NSString *)databaseName; + +- (void)loadRmqId; + +/** + * Save an upstream message to RMQ. If the message send fails for some reason we would not + * lose the message since it would be saved in the RMQ. + * + * @param message The upstream message to be saved. + * @param error The error if any while saving the message else nil. + * + * @return YES if the message was successfully saved to RMQ else NO. + */ +- (BOOL)saveRmqMessage:(GPBMessage *)message error:(NSError **)error; + +/** + * Save Server to device message with the given RMQ-ID. + * + * @param rmqID The rmqID of the s2d message to save. + * + * @return YES if the save was successfull else NO. + */ +- (BOOL)saveS2dMessageWithRmqId:(NSString *)rmqID; + +/** + * A list of all unacked Server to device RMQ IDs. + * + * @return A list of unacked Server to Device RMQ ID's. All values are Strings. + */ +- (NSArray *)unackedS2dRmqIds; + +/** + * Removes the outgoing message from RMQ store. + * + * @param rmqId The rmqID to remove from the store. + * + * @return The number of messages deleted successfully. + */ +- (int)removeRmqMessagesWithRmqId:(NSString *)rmqId; + +/** + * Removes the messages with the given rmqIDs from RMQ store. + * + * @param rmqIds The lsit of rmqID's to remove from the store. + * + * @return The number of messages deleted successfully. + */ +- (int)removeRmqMessagesWithRmqIds:(NSArray *)rmqIds; + +/** + * Removes a list of downstream messages from the RMQ. + * + * @param s2dIds The list of messages ACK'ed by the server that we should remove + * from the RMQ store. + */ +- (void)removeS2dIds:(NSArray *)s2dIds; + +#pragma mark - Sync Messages + +/** + * Get persisted sync message with rmqID. + * + * @param rmqID The rmqID of the persisted sync message. + * + * @return A valid persistent sync message with the given rmqID if found in the RMQ else nil. + */ +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete sync message with rmqID. + * + * @param rmqID The rmqID of the persisted sync message. + * + * @return YES if the message was successfully deleted else NO. + */ +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID; + +/** + * Delete the expired sync messages from persisten store. Also deletes messages that have been + * delivered both via APNS and MCS. + * + * @param error The error if any while deleting the messages. + * + * @return The total number of messages that were deleted from the persistent store. + */ +- (int)deleteExpiredOrFinishedSyncMessages:(NSError **)error; + +/** + * Save sync message received by the device. + * + * @param rmqID The rmqID of the message received. + * @param expirationTime The expiration time of the sync message received. + * @param apnsReceived YES if the message was received via APNS else NO. + * @param mcsReceived YES if the message was received via MCS else NO. + * @param error The error if any while saving the sync message to persistent store. + * + * @return YES if the message save was successful else NO. + */ +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError **)error; + +/** + * Update sync message received via APNS. + * + * @param rmqID The rmqID of the received message. + * @param error The error if any while updating the sync message. + * + * @return YES if the persistent sync message was successfully updated else NO. + */ +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID error:(NSError **)error; + +/** + * Update sync message received via MCS. + * + * @param rmqID The rmqID of the received message. + * @param error The error if any while updating the sync message. + * + * @return YES if the persistent sync message was successfully updated else NO. + */ +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID error:(NSError **)error; + +#pragma mark - Testing + ++ (void)removeDatabaseWithName:(NSString *)dbName; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.m new file mode 100644 index 0000000..449e3d6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingRmqManager.m @@ -0,0 +1,264 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingRmqManager.h" + +#import + +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingRmq2PersistentStore.h" +#import "FIRMessagingUtilities.h" +#import "Protos/GtalkCore.pbobjc.h" + +#ifndef _FIRMessagingRmqLogAndExit +#define _FIRMessagingRmqLogAndExit(stmt, return_value) \ +do { \ + [self logErrorAndFinalizeStatement:stmt]; \ + return return_value; \ +} while(0) +#endif + +static NSString *const kFCMRmqTag = @"FIRMessagingRmq:"; + +@interface FIRMessagingRmqManager () + +@property(nonatomic, readwrite, strong) FIRMessagingRmq2PersistentStore *rmq2Store; +// map the category of an outgoing message with the number of messages for that category +// should always have two keys -- the app, gcm +@property(nonatomic, readwrite, strong) NSMutableDictionary *outstandingMessages; + +// Outgoing RMQ persistent id +@property(nonatomic, readwrite, assign) int64_t rmqId; + +@end + +@implementation FIRMessagingRmqManager + +- (instancetype)initWithDatabaseName:(NSString *)databaseName { + self = [super init]; + if (self) { + _FIRMessagingDevAssert([databaseName length] > 0, @"RMQ: Invalid rmq db name"); + _rmq2Store = [[FIRMessagingRmq2PersistentStore alloc] initWithDatabaseName:databaseName]; + _outstandingMessages = [NSMutableDictionary dictionaryWithCapacity:2]; + _rmqId = -1; + } + return self; +} + +- (void)loadRmqId { + if (self.rmqId >= 0) { + return; // already done + } + + [self loadInitialOutgoingPersistentId]; + if (self.outstandingMessages.count) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmqManager000, + @"%@: outstanding categories %ld", kFCMRmqTag, + _FIRMessaging_UL(self.outstandingMessages.count)); + } +} + +/** + * Initialize the 'initial RMQ': + * - max ID of any message in the queue + * - if the queue is empty, stored value in separate DB. + * + * Stream acks will remove from RMQ, when we remove the highest message we keep track + * of its ID. + */ +- (void)loadInitialOutgoingPersistentId { + + // we shouldn't always trust the lastRmqId stored in the LastRmqId table, because + // we only save to the LastRmqId table once in a while (after getting the lastRmqId sent + // by the server after reconnect, and after getting a rmq ack from the server). The + // rmq message with the highest rmq id tells the real story, so check against that first. + + int64_t rmqId = [self queryHighestRmqId]; + if (rmqId == 0) { + rmqId = [self querylastRmqId]; + } + self.rmqId = rmqId + 1; +} + +#pragma mark - Save + +/** + * Save a message to RMQ2. Will populate the rmq2 persistent ID. + */ +- (BOOL)saveRmqMessage:(GPBMessage *)message + error:(NSError **)error { + // send using rmq2manager + // the wire format of rmq2 id is a string. However, we keep it as a long internally + // in the database. So only convert the id to string when preparing for sending over + // the wire. + NSString *rmq2Id = FIRMessagingGetRmq2Id(message); + if (![rmq2Id length]) { + int64_t rmqId = [self nextRmqId]; + rmq2Id = [NSString stringWithFormat:@"%lld", rmqId]; + FIRMessagingSetRmq2Id(message, rmq2Id); + } + FIRMessagingProtoTag tag = FIRMessagingGetTagForProto(message); + return [self saveMessage:message withRmqId:[rmq2Id integerValue] tag:tag error:error]; +} + +- (BOOL)saveMessage:(GPBMessage *)message + withRmqId:(int64_t)rmqId + tag:(int8_t)tag + error:(NSError **)error { + NSData *data = [message data]; + return [self.rmq2Store saveMessageWithRmqId:rmqId tag:tag data:data error:error]; +} + +/** + * This is called when we delete the largest outgoing message from queue. + */ +- (void)saveLastOutgoingRmqId:(int64_t)rmqID { + [self.rmq2Store updateLastOutgoingRmqId:rmqID]; +} + +- (BOOL)saveS2dMessageWithRmqId:(NSString *)rmqID { + return [self.rmq2Store saveUnackedS2dMessageWithRmqId:rmqID]; +} + +#pragma mark - Query + +- (int64_t)queryHighestRmqId { + return [self.rmq2Store queryHighestRmqId]; +} + +- (int64_t)querylastRmqId { + return [self.rmq2Store queryLastRmqId]; +} + +- (NSArray *)unackedS2dRmqIds { + return [self.rmq2Store unackedS2dRmqIds]; +} + +#pragma mark - FIRMessagingRMQScanner protocol + +/** + * We don't have a 'getMessages' method - it would require loading in memory + * the entire content body of all messages. + * + * Instead we iterate and call 'resend' for each message. + * + * This is called: + * - on connect MCS, to resend any outstanding messages + * - init + */ +- (void)scanWithRmqMessageHandler:(FIRMessagingRmqMessageHandler)rmqMessageHandler + dataMessageHandler:(FIRMessagingDataMessageHandler)dataMessageHandler { + // no need to scan database with no callbacks + if (rmqMessageHandler || dataMessageHandler) { + [self.rmq2Store scanOutgoingRmqMessagesWithHandler:^(int64_t rmqId, int8_t tag, NSData *data) { + if (rmqMessageHandler != nil) { + rmqMessageHandler(rmqId, tag, data); + } + if (dataMessageHandler != nil && kFIRMessagingProtoTagDataMessageStanza == tag) { + GPBMessage *proto = + [FIRMessagingGetClassForTag((FIRMessagingProtoTag)tag) parseFromData:data error:NULL]; + GtalkDataMessageStanza *stanza = (GtalkDataMessageStanza *)proto; + dataMessageHandler(rmqId, stanza); + } + }]; + } +} + +#pragma mark - Remove + +- (void)ackReceivedForRmqId:(NSString *)rmqId { + // TODO: Optional book-keeping +} + +- (int)removeRmqMessagesWithRmqId:(NSString *)rmqId { + return [self removeRmqMessagesWithRmqIds:@[rmqId]]; +} + +- (int)removeRmqMessagesWithRmqIds:(NSArray *)rmqIds { + if (![rmqIds count]) { + return 0; + } + for (NSString *rmqId in rmqIds) { + [self ackReceivedForRmqId:rmqId]; + } + int64_t maxRmqId = -1; + for (NSString *rmqId in rmqIds) { + int64_t rmqIdValue = [rmqId longLongValue]; + if (rmqIdValue > maxRmqId) { + maxRmqId = rmqIdValue; + } + } + maxRmqId++; + if (maxRmqId >= self.rmqId) { + [self saveLastOutgoingRmqId:maxRmqId]; + } + return [self.rmq2Store deleteMessagesFromTable:kTableOutgoingRmqMessages withRmqIds:rmqIds]; +} + +- (void)removeS2dIds:(NSArray *)s2dIds { + [self.rmq2Store deleteMessagesFromTable:kTableS2DRmqIds withRmqIds:s2dIds]; +} + +#pragma mark - Sync Messages + +// TODO: RMQManager should also have a cache for all the sync messages +// so we don't hit the DB each time. +- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID { + return [self.rmq2Store querySyncMessageWithRmqID:rmqID]; +} + +- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID { + return [self.rmq2Store deleteSyncMessageWithRmqID:rmqID]; +} + +- (int)deleteExpiredOrFinishedSyncMessages:(NSError **)error { + return [self.rmq2Store deleteExpiredOrFinishedSyncMessages:error]; +} + +- (BOOL)saveSyncMessageWithRmqID:(NSString *)rmqID + expirationTime:(int64_t)expirationTime + apnsReceived:(BOOL)apnsReceived + mcsReceived:(BOOL)mcsReceived + error:(NSError *__autoreleasing *)error { + return [self.rmq2Store saveSyncMessageWithRmqID:rmqID + expirationTime:expirationTime + apnsReceived:apnsReceived + mcsReceived:mcsReceived + error:error]; +} + +- (BOOL)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID error:(NSError **)error { + return [self.rmq2Store updateSyncMessageViaAPNSWithRmqID:rmqID error:error]; +} + +- (BOOL)updateSyncMessageViaMCSWithRmqID:(NSString *)rmqID error:(NSError **)error { + return [self.rmq2Store updateSyncMessageViaMCSWithRmqID:rmqID error:error]; +} + +#pragma mark - Testing + ++ (void)removeDatabaseWithName:(NSString *)dbName { + [FIRMessagingRmq2PersistentStore removeDatabase:dbName]; +} + +#pragma mark - Private + +- (int64_t)nextRmqId { + return ++self.rmqId; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.h new file mode 100644 index 0000000..169f60e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSUInteger, FIRMessagingSecureSocketState){ + kFIRMessagingSecureSocketNotOpen = 0, + kFIRMessagingSecureSocketOpening, + kFIRMessagingSecureSocketOpen, + kFIRMessagingSecureSocketClosing, + kFIRMessagingSecureSocketClosed, + kFIRMessagingSecureSocketError +}; + +@class FIRMessagingSecureSocket; + +@protocol FIRMessagingSecureSocketDelegate + +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didReceiveData:(NSData *)data + withTag:(int8_t)tag; +- (void)secureSocket:(FIRMessagingSecureSocket *)socket + didSendProtoWithTag:(int8_t)tag + rmqId:(NSString *)rmqId; +- (void)secureSocketDidConnect:(FIRMessagingSecureSocket *)socket; +- (void)didDisconnectWithSecureSocket:(FIRMessagingSecureSocket *)socket; + +@end + +/** + * This manages the input/output streams connected to the MCS server. Used to receive data from + * the server and send to it over the wire. + */ +@interface FIRMessagingSecureSocket : NSObject + +@property(nonatomic, readwrite, weak) id delegate; +@property(nonatomic, readonly, assign) FIRMessagingSecureSocketState state; + +- (void)connectToHost:(NSString *)host port:(NSUInteger)port onRunLoop:(NSRunLoop *)runLoop; +- (void)disconnect; +- (void)sendData:(NSData *)data withTag:(int8_t)tag rmqId:(NSString *)rmqId; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.m new file mode 100644 index 0000000..dd78a76 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSecureSocket.m @@ -0,0 +1,444 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingSecureSocket.h" + +#import +#import +#import + +#import "FIRMessagingCodedInputStream.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPacketQueue.h" + +static const NSUInteger kMaxBufferLength = 1024 * 1024; // 1M +static const NSUInteger kBufferLengthIncrement = 16 * 1024; // 16k +static const uint8_t kVersion = 40; +static const uint8_t kInvalidTag = -1; + +typedef NS_ENUM(NSUInteger, FIRMessagingSecureSocketReadResult) { + kFIRMessagingSecureSocketReadResultNone, + kFIRMessagingSecureSocketReadResultIncomplete, + kFIRMessagingSecureSocketReadResultCorrupt, + kFIRMessagingSecureSocketReadResultSuccess +}; + +static int32_t LogicalRightShift32(int32_t value, int32_t spaces) { + return (int32_t)((uint32_t)(value) >> spaces); +} + +static NSUInteger SerializedSize(int32_t value) { + NSUInteger bytes = 0; + while (YES) { + if ((value & ~0x7F) == 0) { + bytes += sizeof(uint8_t); + return bytes; + } else { + bytes += sizeof(uint8_t); + value = LogicalRightShift32(value, 7); + } + } +} + +@interface FIRMessagingSecureSocket() + +@property(nonatomic, readwrite, assign) FIRMessagingSecureSocketState state; +@property(nonatomic, readwrite, strong) NSInputStream *inStream; +@property(nonatomic, readwrite, strong) NSOutputStream *outStream; + +@property(nonatomic, readwrite, strong) NSMutableData *inputBuffer; +@property(nonatomic, readwrite, assign) NSUInteger inputBufferLength; +@property(nonatomic, readwrite, strong) NSMutableData *outputBuffer; +@property(nonatomic, readwrite, assign) NSUInteger outputBufferLength; + +@property(nonatomic, readwrite, strong) FIRMessagingPacketQueue *packetQueue; +@property(nonatomic, readwrite, assign) BOOL isVersionSent; +@property(nonatomic, readwrite, assign) BOOL isVersionReceived; +@property(nonatomic, readwrite, assign) BOOL isInStreamOpen; +@property(nonatomic, readwrite, assign) BOOL isOutStreamOpen; + +@property(nonatomic, readwrite, strong) NSRunLoop *runLoop; +@property(nonatomic, readwrite, strong) NSString *currentRmqIdBeingSent; +@property(nonatomic, readwrite, assign) int8_t currentProtoTypeBeingSent; + +@end + +@implementation FIRMessagingSecureSocket + +- (instancetype)init { + self = [super init]; + if (self) { + _state = kFIRMessagingSecureSocketNotOpen; + _inputBuffer = [NSMutableData dataWithLength:kBufferLengthIncrement]; + _packetQueue = [[FIRMessagingPacketQueue alloc] init]; + _currentProtoTypeBeingSent = kInvalidTag; + } + return self; +} + +- (void)dealloc { + [self disconnect]; +} + +- (void)connectToHost:(NSString *)host + port:(NSUInteger)port + onRunLoop:(NSRunLoop *)runLoop { + _FIRMessagingDevAssert(host != nil, @"Invalid host"); + _FIRMessagingDevAssert(runLoop != nil, @"Invalid runloop"); + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketNotOpen, @"Socket is already connected"); + + if (!host || self.state != kFIRMessagingSecureSocketNotOpen) { + return; + } + + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket000, + @"Opening secure socket to FIRMessaging service"); + self.state = kFIRMessagingSecureSocketOpening; + self.runLoop = runLoop; + CFReadStreamRef inputStreamRef; + CFWriteStreamRef outputStreamRef; + CFStreamCreatePairWithSocketToHost(NULL, + (__bridge CFStringRef)host, + (int)port, + &inputStreamRef, + &outputStreamRef); + self.inStream = CFBridgingRelease(inputStreamRef); + self.outStream = CFBridgingRelease(outputStreamRef); + if (!self.inStream || !self.outStream) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket001, + @"Failed to initialize socket."); + return; + } + + self.isInStreamOpen = NO; + self.isOutStreamOpen = NO; + + BOOL isVOIPSocket = NO; + + [self openStream:self.outStream isVOIPStream:isVOIPSocket]; + [self openStream:self.inStream isVOIPStream:isVOIPSocket]; +} + +- (void)disconnect { + if (self.state == kFIRMessagingSecureSocketClosing) { + return; + } + if (!self.inStream && !self.outStream) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket002, + @"The socket is not open or already closed."); + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketClosed || self.state == kFIRMessagingSecureSocketNotOpen, + @"Socket is already disconnected."); + return; + } + + self.state = kFIRMessagingSecureSocketClosing; + if (self.inStream) { + [self closeStream:self.inStream]; + self.inStream = nil; + } + if (self.outStream) { + [self closeStream:self.outStream]; + self.outStream = nil; + } + self.state = kFIRMessagingSecureSocketClosed; + [self.delegate didDisconnectWithSecureSocket:self]; +} + +- (void)sendData:(NSData *)data withTag:(int8_t)tag rmqId:(NSString *)rmqId { + [self.packetQueue push:[FIRMessagingPacket packetWithTag:tag rmqId:rmqId data:data]]; + if ([self.outStream hasSpaceAvailable]) { + [self performWrite]; + } +} + +#pragma mark - NSStreamDelegate + +- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { + switch (eventCode) { + case NSStreamEventHasBytesAvailable: + if (self.state != kFIRMessagingSecureSocketOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket003, + @"Try to read from socket that is not opened"); + return; + } + _FIRMessagingDevAssert(stream == self.inStream, @"Incorrect stream"); + if (![self performRead]) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket004, + @"Error occurred when reading incoming stream"); + [self disconnect]; + } + break; + case NSStreamEventEndEncountered: + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeSecureSocket005, @"%@ end encountered", + stream == self.inStream + ? @"Input stream" + : (stream == self.outStream ? @"Output stream" : @"Unknown stream")); + [self disconnect]; + break; + case NSStreamEventOpenCompleted: + if (stream == self.inStream) { + self.isInStreamOpen = YES; + } else if (stream == self.outStream) { + self.isOutStreamOpen = YES; + } + if (self.isInStreamOpen && self.isOutStreamOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket006, + @"Secure socket to FIRMessaging service opened"); + self.state = kFIRMessagingSecureSocketOpen; + [self.delegate secureSocketDidConnect:self]; + } + break; + case NSStreamEventErrorOccurred: { + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeSecureSocket007, @"%@ error occurred", + stream == self.inStream + ? @"Input stream" + : (stream == self.outStream ? @"Output stream" : @"Unknown stream")); + [self disconnect]; + break; + } + case NSStreamEventHasSpaceAvailable: + if (self.state != kFIRMessagingSecureSocketOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket008, + @"Try to write to socket that is not opened"); + return; + } + _FIRMessagingDevAssert(stream == self.outStream, @"Incorrect stream"); + [self performWrite]; + break; + default: + break; + } +} + +#pragma mark - Private + +- (void)openStream:(NSStream *)stream isVOIPStream:(BOOL)isVOIPStream { + _FIRMessagingDevAssert(stream != nil, @"Invalid stream"); + _FIRMessagingDevAssert(self.runLoop != nil, @"Invalid runloop"); + + if (stream) { + _FIRMessagingDevAssert([stream streamStatus] == NSStreamStatusNotOpen, @"Stream already open"); + if ([stream streamStatus] != NSStreamStatusNotOpen) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket009, + @"stream should not be open."); + return; + } + [stream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL + forKey:NSStreamSocketSecurityLevelKey]; + if (isVOIPStream) { + [stream setProperty:NSStreamNetworkServiceTypeVoIP + forKey:NSStreamNetworkServiceType]; + } + stream.delegate = self; + [stream scheduleInRunLoop:self.runLoop forMode:NSDefaultRunLoopMode]; + [stream open]; + } +} + +- (void)closeStream:(NSStream *)stream { + _FIRMessagingDevAssert(stream != nil, @"Invalid stream"); + _FIRMessagingDevAssert(self.runLoop != nil, @"Invalid runloop"); + + if (stream) { + [stream close]; + [stream removeFromRunLoop:self.runLoop forMode:NSDefaultRunLoopMode]; + stream.delegate = nil; + } +} + +- (BOOL)performRead { + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketOpen, @"Socket should be open"); + + if (!self.isVersionReceived) { + self.isVersionReceived = YES; + uint8_t versionByte = 0; + NSInteger bytesRead = [self.inStream read:&versionByte maxLength:sizeof(uint8_t)]; + if (bytesRead != sizeof(uint8_t) || kVersion != versionByte) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket010, + @"Version do not match. Received %d, Expecting %d", versionByte, + kVersion); + return NO; + } + } + + while (YES) { + BOOL isInputBufferValid = [self.inputBuffer length] > 0; + _FIRMessagingDevAssert(isInputBufferValid, + @"Invalid input buffer size %lu. Used bytes length %lu, buffer content: %@", + _FIRMessaging_UL([self.inputBuffer length]), + _FIRMessaging_UL(self.inputBufferLength), + self.inputBuffer); + if (!isInputBufferValid) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket011, + @"Input buffer is not valid."); + return NO; + } + + if (![self.inStream hasBytesAvailable]) { + break; + } + + // try to read more data + uint8_t *unusedBufferPtr = (uint8_t *)self.inputBuffer.mutableBytes + self.inputBufferLength; + NSUInteger unusedBufferLength = [self.inputBuffer length] - self.inputBufferLength; + NSInteger bytesRead = [self.inStream read:unusedBufferPtr maxLength:unusedBufferLength]; + if (bytesRead <= 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket012, + @"Failed to read input stream. Bytes read %ld, Used buffer size %lu, " + @"Unused buffer size %lu", + _FIRMessaging_UL(bytesRead), _FIRMessaging_UL(self.inputBufferLength), + _FIRMessaging_UL(unusedBufferLength)); + break; + } + // did successfully read some more data + self.inputBufferLength += (NSUInteger)bytesRead; + + if ([self.inputBuffer length] <= self.inputBufferLength) { + // shouldn't be reading more than 1MB of data in one go + if ([self.inputBuffer length] + kBufferLengthIncrement > kMaxBufferLength) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket013, + @"Input buffer exceed 1M, disconnect socket"); + return NO; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket014, + @"Input buffer limit exceeded. Used input buffer size %lu, " + @"Total input buffer size %lu. No unused buffer left. " + @"Increase buffer size.", + _FIRMessaging_UL(self.inputBufferLength), + _FIRMessaging_UL([self.inputBuffer length])); + [self.inputBuffer increaseLengthBy:kBufferLengthIncrement]; + _FIRMessagingDevAssert([self.inputBuffer length] > self.inputBufferLength, @"Invalid buffer size"); + } + + while (self.inputBufferLength > 0 && [self.inputBuffer length] > 0) { + _FIRMessagingDevAssert([self.inputBuffer length] >= self.inputBufferLength, + @"Buffer longer than length"); + NSRange inputRange = NSMakeRange(0, self.inputBufferLength); + size_t protoBytes = 0; + // read the actual proto data coming in + FIRMessagingSecureSocketReadResult readResult = + [self processCurrentInputBuffer:[self.inputBuffer subdataWithRange:inputRange] + outOffset:&protoBytes]; + // Corrupt data encountered, stop processing. + if (readResult == kFIRMessagingSecureSocketReadResultCorrupt) { + return NO; + // Incomplete data, keep trying to read by loading more from the stream. + } else if (readResult == kFIRMessagingSecureSocketReadResultIncomplete) { + break; + } + _FIRMessagingDevAssert(self.inputBufferLength >= protoBytes, @"More bytes than buffer can handle"); + // we have read (0, protoBytes) of data in the inputBuffer + if (protoBytes == self.inputBufferLength) { + // did completely read the buffer data can be reset for further processing + self.inputBufferLength = 0; + } else { + // delete processed bytes while maintaining the buffer size. + NSUInteger prevLength __unused = [self.inputBuffer length]; + // delete the processed bytes + [self.inputBuffer replaceBytesInRange:NSMakeRange(0, protoBytes) withBytes:NULL length:0]; + // reallocate more data + [self.inputBuffer increaseLengthBy:protoBytes]; + _FIRMessagingDevAssert([self.inputBuffer length] == prevLength, + @"Invalid input buffer size %lu. Used bytes length %lu, " + @"buffer content: %@", + _FIRMessaging_UL([self.inputBuffer length]), + _FIRMessaging_UL(self.inputBufferLength), + self.inputBuffer); + self.inputBufferLength -= protoBytes; + } + } + } + return YES; +} + +- (FIRMessagingSecureSocketReadResult)processCurrentInputBuffer:(NSData *)readData + outOffset:(size_t *)outOffset { + *outOffset = 0; + + FIRMessagingCodedInputStream *input = [[FIRMessagingCodedInputStream alloc] initWithData:readData]; + int8_t rawTag; + if (![input readTag:&rawTag]) { + return kFIRMessagingSecureSocketReadResultIncomplete; + } + int32_t length; + if (![input readLength:&length]) { + return kFIRMessagingSecureSocketReadResultIncomplete; + } + // NOTE tag can be zero for |HeartbeatPing|, and length can be zero for |Close| proto + _FIRMessagingDevAssert(rawTag >= 0 && length >= 0, @"Invalid tag or length"); + if (rawTag < 0 || length < 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket015, @"Buffer data corrupted."); + return kFIRMessagingSecureSocketReadResultCorrupt; + } + NSData *data = [input readDataWithLength:(uint32_t)length]; + if (data == nil) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket016, + @"Incomplete data, buffered data length %ld, expected length %d", + _FIRMessaging_UL(self.inputBufferLength), length); + return kFIRMessagingSecureSocketReadResultIncomplete; + } + [self.delegate secureSocket:self didReceiveData:data withTag:rawTag]; + *outOffset = input.offset; + return kFIRMessagingSecureSocketReadResultSuccess; +} + +- (void)performWrite { + _FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketOpen, @"Invalid socket state"); + + if (!self.isVersionSent) { + self.isVersionSent = YES; + uint8_t versionByte = kVersion; + [self.outStream write:&versionByte maxLength:sizeof(uint8_t)]; + } + + while (!self.packetQueue.isEmpty && self.outStream.hasSpaceAvailable) { + if (self.outputBuffer.length == 0) { + // serialize new packets only when the output buffer is flushed. + FIRMessagingPacket *packet = [self.packetQueue pop]; + self.currentRmqIdBeingSent = packet.rmqId; + self.currentProtoTypeBeingSent = packet.tag; + NSUInteger length = SerializedSize(packet.tag) + + SerializedSize((int)packet.data.length) + packet.data.length; + self.outputBuffer = [NSMutableData dataWithLength:length]; + GPBCodedOutputStream *output = [GPBCodedOutputStream streamWithData:self.outputBuffer]; + [output writeRawVarint32:packet.tag]; + [output writeBytesNoTag:packet.data]; + self.outputBufferLength = 0; + } + + // flush the output buffer. + NSInteger written = [self.outStream write:self.outputBuffer.bytes + self.outputBufferLength + maxLength:self.outputBuffer.length - self.outputBufferLength]; + if (written <= 0) { + continue; + } + self.outputBufferLength += (NSUInteger)written; + if (self.outputBufferLength >= self.outputBuffer.length) { + self.outputBufferLength = 0; + self.outputBuffer = nil; + [self.delegate secureSocket:self + didSendProtoWithTag:self.currentProtoTypeBeingSent + rmqId:self.currentRmqIdBeingSent]; + self.currentRmqIdBeingSent = nil; + self.currentProtoTypeBeingSent = kInvalidTag; + } + } +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.h new file mode 100644 index 0000000..3d30bdb --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRMessagingRmqManager; + +/** + * Handle sync messages being received both via MCS and APNS. + */ +@interface FIRMessagingSyncMessageManager : NSObject + +/** + * Initialize sync message manager. + * + * @param rmqManager The RMQ manager on the client. + * + * @return Sync message manager. + */ +- (instancetype)initWithRmqManager:(FIRMessagingRmqManager *)rmqManager; + +/** + * Remove expired sync message from persistent store. Also removes messages that have + * been received both via APNS and MCS. + */ +- (void)removeExpiredSyncMessages; + +/** + * App did recive a sync message via APNS. + * + * @param message The sync message received. + * + * @return YES if the message is a duplicate of an already received sync message else NO. + */ +- (BOOL)didReceiveAPNSSyncMessage:(NSDictionary *)message; + +/** + * App did receive a sync message via MCS. + * + * @param message The sync message received. + * + * @return YES if the message is a duplicate of an already received sync message else NO. + */ +- (BOOL)didReceiveMCSSyncMessage:(NSDictionary *)message; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.m new file mode 100644 index 0000000..1257b02 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingSyncMessageManager.m @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingSyncMessageManager.h" + +#import "FIRMessagingConstants.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingPersistentSyncMessage.h" +#import "FIRMessagingRmqManager.h" +#import "FIRMessagingUtilities.h" + +static const int64_t kDefaultSyncMessageTTL = 4 * 7 * 24 * 60 * 60; // 4 weeks +// 4 MB of free space is required to persist Sync messages +static const uint64_t kMinFreeDiskSpaceInMB = 1; + +@interface FIRMessagingSyncMessageManager() + +@property(nonatomic, readwrite, strong) FIRMessagingRmqManager *rmqManager; + +@end + +@implementation FIRMessagingSyncMessageManager + +- (instancetype)init { + FIRMessagingInvalidateInitializer(); +} + +- (instancetype)initWithRmqManager:(FIRMessagingRmqManager *)rmqManager { + _FIRMessagingDevAssert(rmqManager, @"Invalid nil rmq manager while initalizing sync message manager"); + self = [super init]; + if (self) { + _rmqManager = rmqManager; + } + return self; +} + +- (void)removeExpiredSyncMessages { + NSError *error; + int deleteCount = [self.rmqManager deleteExpiredOrFinishedSyncMessages:&error]; + if (error) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager000, + @"Error while deleting expired sync messages %@", error); + } else if (deleteCount > 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSyncMessageManager001, + @"Successfully deleted %d sync messages from store", deleteCount); + } +} + +- (BOOL)didReceiveAPNSSyncMessage:(NSDictionary *)message { + return [self didReceiveSyncMessage:message viaAPNS:YES viaMCS:NO]; +} + +- (BOOL)didReceiveMCSSyncMessage:(NSDictionary *)message { + return [self didReceiveSyncMessage:message viaAPNS:NO viaMCS:YES]; +} + +- (BOOL)didReceiveSyncMessage:(NSDictionary *)message + viaAPNS:(BOOL)viaAPNS + viaMCS:(BOOL)viaMCS { + NSString *rmqID = message[kFIRMessagingMessageIDKey]; + _FIRMessagingDevAssert([rmqID length], @"Invalid nil rmqID for message"); + if (![rmqID length]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager002, + @"Invalid nil rmqID for sync message."); + return NO; + } + + FIRMessagingPersistentSyncMessage *persistentMessage = + [self.rmqManager querySyncMessageWithRmqID:rmqID]; + + NSError *error; + if (!persistentMessage) { + + // Do not persist the new message if we don't have enough disk space + uint64_t freeDiskSpace = FIRMessagingGetFreeDiskSpaceInMB(); + if (freeDiskSpace < kMinFreeDiskSpaceInMB) { + return NO; + } + + int64_t expirationTime = [[self class] expirationTimeForSyncMessage:message]; + if (![self.rmqManager saveSyncMessageWithRmqID:rmqID + expirationTime:expirationTime + apnsReceived:viaAPNS + mcsReceived:viaMCS + error:&error]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager003, + @"Failed to save sync message with rmqID %@", rmqID); + } else { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeSyncMessageManager004, + @"Added sync message to cache: %@", rmqID); + } + return NO; + } + + if (viaAPNS && !persistentMessage.apnsReceived) { + persistentMessage.apnsReceived = YES; + if (![self.rmqManager updateSyncMessageViaAPNSWithRmqID:rmqID error:&error]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager005, + @"Failed to update APNS state for sync message %@", rmqID); + } + } else if (viaMCS && !persistentMessage.mcsReceived) { + persistentMessage.mcsReceived = YES; + if (![self.rmqManager updateSyncMessageViaMCSWithRmqID:rmqID error:&error]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager006, + @"Failed to update MCS state for sync message %@", rmqID); + } + } + + // Received message via both ways we can safely delete it. + if (persistentMessage.apnsReceived && persistentMessage.mcsReceived) { + if (![self.rmqManager deleteSyncMessageWithRmqID:rmqID]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager007, + @"Failed to delete sync message %@", rmqID); + } else { + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeSyncMessageManager008, + @"Successfully deleted sync message from cache %@", rmqID); + } + } + + // Already received this message either via MCS or APNS. + return YES; +} + ++ (int64_t)expirationTimeForSyncMessage:(NSDictionary *)message { + int64_t ttl = kDefaultSyncMessageTTL; + if (message[kFIRMessagingMessageSyncMessageTTLKey]) { + ttl = [message[kFIRMessagingMessageSyncMessageTTLKey] longLongValue]; + } + int64_t currentTime = FIRMessagingCurrentTimestampInSeconds(); + return currentTime + ttl; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.h new file mode 100644 index 0000000..ea98e6d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRMessaging.h" +#import "FIRMessagingCheckinService.h" +#import "FIRMessagingTopicsCommon.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * An asynchronous NSOperation subclass which performs a single network request for a topic + * subscription operation. Once completed, it calls its provided completion handler. + */ +@interface FIRMessagingTopicOperation : NSOperation + +@property(nonatomic, readonly, copy) NSString *topic; +@property(nonatomic, readonly, assign) FIRMessagingTopicAction action; +@property(nonatomic, readonly, copy) NSString *token; +@property(nonatomic, readonly, copy, nullable) NSDictionary *options; +@property(nonatomic, readonly, strong) FIRMessagingCheckinService *checkinService; + +- (instancetype)initWithTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + token:(NSString *)token + options:(nullable NSDictionary *)options + checkinService:(FIRMessagingCheckinService *)checkinService + completion:(FIRMessagingTopicOperationCompletion)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.m new file mode 100644 index 0000000..6703178 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicOperation.m @@ -0,0 +1,263 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingTopicOperation.h" + +#import "FIRMessagingCheckinService.h" +#import "FIRMessagingDefines.h" +#import "FIRMessagingLogger.h" +#import "FIRMessagingUtilities.h" +#import "NSError+FIRMessaging.h" + +#define DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS 0 + +static NSString *const kFIRMessagingSubscribeServerHost = + @"https://iid.googleapis.com/iid/register"; + +NSString *FIRMessagingSubscriptionsServer() { + static NSString *serverHost = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *environment = [[NSProcessInfo processInfo] environment]; + NSString *customServerHost = environment[@"FCM_SERVER_ENDPOINT"]; + if (customServerHost.length) { + serverHost = customServerHost; + } else { + serverHost = kFIRMessagingSubscribeServerHost; + } + }); + return serverHost; +} + +@interface FIRMessagingTopicOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, copy) NSString *topic; +@property(nonatomic, readwrite, assign) FIRMessagingTopicAction action; +@property(nonatomic, readwrite, copy) NSString *token; +@property(nonatomic, readwrite, copy) NSDictionary *options; +@property(nonatomic, readwrite, strong) FIRMessagingCheckinService *checkinService; +@property(nonatomic, readwrite, copy) FIRMessagingTopicOperationCompletion completion; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; + +@end + +@implementation FIRMessagingTopicOperation + ++ (NSURLSession *)sharedSession { + static NSURLSession *subscriptionOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + subscriptionOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + subscriptionOperationSharedSession.sessionDescription = @"com.google.fcm.topics.session"; + }); + return subscriptionOperationSharedSession; +} + +- (instancetype)initWithTopic:(NSString *)topic + action:(FIRMessagingTopicAction)action + token:(NSString *)token + options:(NSDictionary *)options + checkinService:(FIRMessagingCheckinService *)checkinService + completion:(FIRMessagingTopicOperationCompletion)completion { + if (self = [super init]) { + _topic = topic; + _action = action; + _token = token; + _options = options; + _checkinService = checkinService; + _completion = completion; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _topic = nil; + _token = nil; + _checkinService = nil; + _completion = nil; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + NSError *error = + [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubOperationIsCancelled]; + [self finishWithError:error]; + return; + } + + [self setExecuting:YES]; + + [self performSubscriptionChange]; +} + +- (void)finishWithError:(NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + if (self.completion) { + self.completion(error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + NSError *error = [NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubOperationIsCancelled]; + [self finishWithError:error]; +} + +- (void)performSubscriptionChange { + + NSURL *url = [NSURL URLWithString:FIRMessagingSubscriptionsServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + NSString *appIdentifier = FIRMessagingAppIdentifier(); + NSString *deviceAuthID = self.checkinService.deviceAuthID; + NSString *secretToken = self.checkinService.secretToken; + NSString *authString = [NSString stringWithFormat:@"AidLogin %@:%@", deviceAuthID, secretToken]; + [request setValue:authString forHTTPHeaderField:@"Authorization"]; + [request setValue:appIdentifier forHTTPHeaderField:@"app"]; + [request setValue:self.checkinService.versionInfo forHTTPHeaderField:@"info"]; + + // Topic can contain special characters (like `%`) so encode the value. + NSCharacterSet *characterSet = [NSCharacterSet URLQueryAllowedCharacterSet]; + NSString *encodedTopic = + [self.topic stringByAddingPercentEncodingWithAllowedCharacters:characterSet]; + if (encodedTopic == nil) { + // The transformation was somehow not possible, so use the original topic. + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTopicOptionTopicEncodingFailed, + @"Unable to encode the topic '%@' during topic subscription change. " + @"Please ensure that the topic name contains only valid characters.", + self.topic); + encodedTopic = self.topic; + } + + NSMutableString *content = [NSMutableString stringWithFormat: + @"sender=%@&app=%@&device=%@&" + @"app_ver=%@&X-gcm.topic=%@&X-scope=%@", + self.token, + appIdentifier, + deviceAuthID, + FIRMessagingCurrentAppVersion(), + encodedTopic, + encodedTopic]; + + if (self.action == FIRMessagingTopicActionUnsubscribe) { + [content appendString:@"&delete=true"]; + } + + FIRMessagingLoggerInfo(kFIRMessagingMessageCodeTopicOption000, @"Topic subscription request: %@", + content); + + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + [request setHTTPMethod:@"POST"]; + +#if DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS + NSDate *start = [NSDate date]; +#endif + + FIRMessaging_WEAKIFY(self) + void(^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *URLResponse, NSError *error) { + FIRMessaging_STRONGIFY(self) + if (error) { + // Our operation could have been cancelled, which would result in our data task's error being + // NSURLErrorCancelled + if (error.code == NSURLErrorCancelled) { + // We would only have been cancelled in the -cancel method, which will call finish for us + // so just return and do nothing. + return; + } + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOption001, + @"Device registration HTTP fetch error. Error Code: %ld", + _FIRMessaging_L(error.code)); + [self finishWithError:error]; + return; + } + NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (response.length == 0) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOperationEmptyResponse, + @"Invalid registration response - zero length."); + [self finishWithError:[NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeUnknown]]; + return; + } + NSArray *parts = [response componentsSeparatedByString:@"="]; + _FIRMessagingDevAssert(parts.count, @"Invalid registration response"); + if (![parts[0] isEqualToString:@"token"] || parts.count <= 1) { + FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOption002, + @"Invalid registration response %@", response); + [self finishWithError:[NSError errorWithFCMErrorCode:kFIRMessagingErrorCodeUnknown]]; + return; + } +#if DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS + NSTimeInterval duration = -[start timeIntervalSinceNow]; + FIRMessagingLoggerDebug(@"%@ change took %.2fs", self.topic, duration); +#endif + [self finishWithError:nil]; + + }; + + NSURLSession *urlSession = [FIRMessagingTopicOperation sharedSession]; + + self.dataTask = [urlSession dataTaskWithRequest:request completionHandler:requestHandler]; + NSString *description; + if (_action == FIRMessagingTopicActionSubscribe) { + description = [NSString stringWithFormat:@"com.google.fcm.topics.subscribe: %@", _topic]; + } else { + description = [NSString stringWithFormat:@"com.google.fcm.topics.unsubscribe: %@", _topic]; + } + self.dataTask.taskDescription = description; + [self.dataTask resume]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicsCommon.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicsCommon.h new file mode 100644 index 0000000..030b3ff --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingTopicsCommon.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on a subscription topic. + */ +typedef NS_ENUM(NSInteger, FIRMessagingTopicAction) { + FIRMessagingTopicActionSubscribe, + FIRMessagingTopicActionUnsubscribe +}; + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.h new file mode 100644 index 0000000..58475bf --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(int8_t, FIRMessagingProtoTag) { + kFIRMessagingProtoTagInvalid = -1, + kFIRMessagingProtoTagHeartbeatPing = 0, + kFIRMessagingProtoTagHeartbeatAck = 1, + kFIRMessagingProtoTagLoginRequest = 2, + kFIRMessagingProtoTagLoginResponse = 3, + kFIRMessagingProtoTagClose = 4, + kFIRMessagingProtoTagIqStanza = 7, + kFIRMessagingProtoTagDataMessageStanza = 8, +}; + +@class GPBMessage; + +#pragma mark - Protocol Buffers + +FOUNDATION_EXPORT FIRMessagingProtoTag FIRMessagingGetTagForProto(GPBMessage *protoClass); +FOUNDATION_EXPORT Class FIRMessagingGetClassForTag(FIRMessagingProtoTag tag); + +#pragma mark - MCS + +FOUNDATION_EXPORT NSString *FIRMessagingGetRmq2Id(GPBMessage *proto); +FOUNDATION_EXPORT void FIRMessagingSetRmq2Id(GPBMessage *proto, NSString *pID); +FOUNDATION_EXPORT int FIRMessagingGetLastStreamId(GPBMessage *proto); +FOUNDATION_EXPORT void FIRMessagingSetLastStreamId(GPBMessage *proto, int sid); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRMessagingCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRMessagingCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRMessagingCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRMessagingAppIdentifier(void); + +#pragma mark - Others + +FOUNDATION_EXPORT uint64_t FIRMessagingGetFreeDiskSpaceInMB(void); +FOUNDATION_EXPORT UIApplication *FIRMessagingUIApplication(void); +FOUNDATION_EXPORT NSSearchPathDirectory FIRMessagingSupportedDirectory(void); + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.m new file mode 100644 index 0000000..743caed --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingUtilities.m @@ -0,0 +1,196 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingUtilities.h" + +#import "Protos/GtalkCore.pbobjc.h" + +#import "FIRMessagingLogger.h" + +#import + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static const uint64_t kBytesToMegabytesDivisor = 1024 * 1024LL; + +#pragma mark - Protocol Buffers + +FIRMessagingProtoTag FIRMessagingGetTagForProto(GPBMessage *proto) { + if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) { + return kFIRMessagingProtoTagHeartbeatPing; + } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) { + return kFIRMessagingProtoTagHeartbeatAck; + } else if ([proto isKindOfClass:[GtalkLoginRequest class]]) { + return kFIRMessagingProtoTagLoginRequest; + } else if ([proto isKindOfClass:[GtalkLoginResponse class]]) { + return kFIRMessagingProtoTagLoginResponse; + } else if ([proto isKindOfClass:[GtalkClose class]]) { + return kFIRMessagingProtoTagClose; + } else if ([proto isKindOfClass:[GtalkIqStanza class]]) { + return kFIRMessagingProtoTagIqStanza; + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + return kFIRMessagingProtoTagDataMessageStanza; + } + return kFIRMessagingProtoTagInvalid; +} + +Class FIRMessagingGetClassForTag(FIRMessagingProtoTag tag) { + switch (tag) { + case kFIRMessagingProtoTagHeartbeatPing: + return GtalkHeartbeatPing.class; + case kFIRMessagingProtoTagHeartbeatAck: + return GtalkHeartbeatAck.class; + case kFIRMessagingProtoTagLoginRequest: + return GtalkLoginRequest.class; + case kFIRMessagingProtoTagLoginResponse: + return GtalkLoginResponse.class; + case kFIRMessagingProtoTagClose: + return GtalkClose.class; + case kFIRMessagingProtoTagIqStanza: + return GtalkIqStanza.class; + case kFIRMessagingProtoTagDataMessageStanza: + return GtalkDataMessageStanza.class; + case kFIRMessagingProtoTagInvalid: + return NSNull.class; + } + return NSNull.class; +} + +#pragma mark - MCS + +NSString *FIRMessagingGetRmq2Id(GPBMessage *proto) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + if (((GtalkIqStanza *)proto).hasPersistentId) { + return ((GtalkIqStanza *)proto).persistentId; + } + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + if (((GtalkDataMessageStanza *)proto).hasPersistentId) { + return ((GtalkDataMessageStanza *)proto).persistentId; + } + } + return nil; +} + +void FIRMessagingSetRmq2Id(GPBMessage *proto, NSString *pID) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + ((GtalkIqStanza *)proto).persistentId = pID; + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + ((GtalkDataMessageStanza *)proto).persistentId = pID; + } +} + +int FIRMessagingGetLastStreamId(GPBMessage *proto) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + if (((GtalkIqStanza *)proto).hasLastStreamIdReceived) { + return ((GtalkIqStanza *)proto).lastStreamIdReceived; + } + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + if (((GtalkDataMessageStanza *)proto).hasLastStreamIdReceived) { + return ((GtalkDataMessageStanza *)proto).lastStreamIdReceived; + } + } else if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) { + if (((GtalkHeartbeatPing *)proto).hasLastStreamIdReceived) { + return ((GtalkHeartbeatPing *)proto).lastStreamIdReceived; + } + } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) { + if (((GtalkHeartbeatAck *)proto).hasLastStreamIdReceived) { + return ((GtalkHeartbeatAck *)proto).lastStreamIdReceived; + } + } + return -1; +} + +void FIRMessagingSetLastStreamId(GPBMessage *proto, int sid) { + if ([proto isKindOfClass:[GtalkIqStanza class]]) { + ((GtalkIqStanza *)proto).lastStreamIdReceived = sid; + } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) { + ((GtalkDataMessageStanza *)proto).lastStreamIdReceived = sid; + } else if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) { + ((GtalkHeartbeatPing *)proto).lastStreamIdReceived = sid; + } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) { + ((GtalkHeartbeatAck *)proto).lastStreamIdReceived = sid; + } +} + +#pragma mark - Time + +int64_t FIRMessagingCurrentTimestampInSeconds(void) { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRMessagingCurrentTimestampInMilliseconds(void) { + return (int64_t)(FIRMessagingCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRMessagingCurrentAppVersion(void) { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities000, + @"Could not find current app version"); + return @""; + } + return version; +} + +NSString *FIRMessagingAppIdentifier(void) { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +uint64_t FIRMessagingGetFreeDiskSpaceInMB(void) { + NSError *error; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + + NSDictionary *attributesMap = + [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] + error:&error]; + if (attributesMap) { + uint64_t totalSizeInBytes __unused = [attributesMap[NSFileSystemSize] longLongValue]; + uint64_t freeSizeInBytes = [attributesMap[NSFileSystemFreeSize] longLongValue]; + FIRMessagingLoggerDebug( + kFIRMessagingMessageCodeUtilities001, @"Device has capacity %llu MB with %llu MB free.", + totalSizeInBytes / kBytesToMegabytesDivisor, freeSizeInBytes / kBytesToMegabytesDivisor); + return ((double)freeSizeInBytes) / kBytesToMegabytesDivisor; + } else { + FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities002, + @"Error in retreiving device's free memory %@", error); + return 0; + } +} + +UIApplication *FIRMessagingUIApplication(void) { + static Class applicationClass = nil; + // iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication + // responds to it. + if (![GULAppEnvironmentUtil isAppExtension]) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + return [applicationClass sharedApplication]; +} + +NSSearchPathDirectory FIRMessagingSupportedDirectory(void) { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.h new file mode 100644 index 0000000..cd292af --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Parsing utility for FIRMessaging Library versions. FIRMessaging Library follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRMessagingCurrentLibraryVersion(void); +/// Returns the current Major version of FIRMessaging library. +FOUNDATION_EXPORT int FIRMessagingCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of FIRMessaging library. +FOUNDATION_EXPORT int FIRMessagingCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of FIRMessaging library. +FOUNDATION_EXPORT int FIRMessagingCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRMessagingCurrentLibraryVersionIsBeta(void); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.m new file mode 100644 index 0000000..1a3333c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessagingVersionUtilities.m @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessagingVersionUtilities.h" + +#import "FIRMessagingDefines.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRMessagingParseCurrentLibraryVersion(void) { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = [NSMutableString stringWithUTF8String:STR(FIRMessaging_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + _FIRMessagingDevAssert(allVersions.count == 3, @"Invalid versioning of FIRMessaging library"); + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + _FIRMessagingDevAssert(patchAndBetaVersion.count <= 2, @"Invalid versioning of FIRMessaging library"); + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRMessagingCurrentLibraryVersion(void) { + FIRMessagingParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRMessagingCurrentLibraryVersionMajor(void) { + FIRMessagingParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRMessagingCurrentLibraryVersionMinor(void) { + FIRMessagingParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRMessagingCurrentLibraryVersionPatch(void) { + FIRMessagingParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRMessagingCurrentLibraryVersionIsBeta(void) { + FIRMessagingParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging_Private.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging_Private.h new file mode 100644 index 0000000..0a95a50 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FIRMessaging_Private.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" + +@class FIRMessagingClient; +@class FIRMessagingPubSub; + +typedef NS_ENUM(int8_t, FIRMessagingNetworkStatus) { + kFIRMessagingReachabilityNotReachable = 0, + kFIRMessagingReachabilityReachableViaWiFi, + kFIRMessagingReachabilityReachableViaWWAN, +}; + +FOUNDATION_EXPORT NSString *const kFIRMessagingPlistAutoInitEnabled; +FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled; +FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyUseMessagingDelegate; +FOUNDATION_EXPORT NSString *const kFIRMessagingPlistUseMessagingDelegate; + +@interface FIRMessagingRemoteMessage () + +@property(nonatomic, copy) NSString *messageID; +@property(nonatomic, strong) NSDictionary *appData; + +@end + +@interface FIRMessaging () + +#pragma mark - Private API + +- (NSString *)defaultFcmToken; +- (FIRMessagingClient *)client; +- (FIRMessagingPubSub *)pubsub; + +// Create a sample message to be sent over the wire using FIRMessaging. Look at +// FIRMessagingService.h to see what each param signifies. ++ (NSMutableDictionary *)createFIRMessagingMessageWithMessage:(NSDictionary *)message + to:(NSString *)to + withID:(NSString *)msgID + timeToLive:(int64_t)ttl + delay:(int)delay; + +- (BOOL)isNetworkAvailable; +- (FIRMessagingNetworkStatus)networkType; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FirebaseMessaging.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FirebaseMessaging.h new file mode 100644 index 0000000..ef081c9 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/FirebaseMessaging.h @@ -0,0 +1,17 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h new file mode 100644 index 0000000..d6a1639 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// @file FIRMessagingInternalUtilities.h +/// +/// Internal Class Names and Methods that other libs can query at runtime. + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the +/// required method. +static NSString *const kFIRMessagingSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRMessagingSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRMessagingSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.h new file mode 100644 index 0000000..fe14451 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface NSDictionary (FIRMessaging) + +/** + * Returns a string representation for the given dictionary. Assumes that all + * keys and values are strings. + * + * @return A string representation of all keys and values in the dictionary. + * The returned string is not pretty-printed. + */ +- (NSString *)fcm_string; + +/** + * Check if the dictionary has any non-string keys or values. + * + * @return YES if the dictionary has any non-string keys or values else NO. + */ +- (BOOL)fcm_hasNonStringKeysOrValues; + +/** + * Trims all (key, value) pair in a dictionary that are not strings. + * + * @return A new copied dictionary with all the non-string keys or values + * removed from the original dictionary. + */ +- (NSDictionary *)fcm_trimNonStringValues; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.m new file mode 100644 index 0000000..8df22ab --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSDictionary+FIRMessaging.m @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSDictionary+FIRMessaging.h" + +@implementation NSDictionary (FIRMessaging) + +- (NSString *)fcm_string { + NSMutableString *dictAsString = [NSMutableString string]; + NSString *separator = @"|"; + for (id key in self) { + id value = self[key]; + if ([key isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { + [dictAsString appendFormat:@"%@:%@%@", key, value, separator]; + } + } + // remove the last separator + if ([dictAsString length]) { + [dictAsString deleteCharactersInRange:NSMakeRange(dictAsString.length - 1, 1)]; + } + return [dictAsString copy]; +} + +- (BOOL)fcm_hasNonStringKeysOrValues { + for (id key in self) { + id value = self[key]; + if (![key isKindOfClass:[NSString class]] || ![value isKindOfClass:[NSString class]]) { + return YES; + } + } + return NO; +} + +- (NSDictionary *)fcm_trimNonStringValues { + NSMutableDictionary *trimDictionary = + [NSMutableDictionary dictionaryWithCapacity:self.count]; + for (id key in self) { + id value = self[key]; + if ([key isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { + trimDictionary[(NSString *)key] = value; + } + } + return trimDictionary; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.h new file mode 100644 index 0000000..ae25b5b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRMessagingDomain; + +typedef NS_ENUM(NSUInteger, FIRMessagingInternalErrorCode) { + // Unknown error. + kFIRMessagingErrorCodeUnknown = 0, + + // HTTP related errors. + kFIRMessagingErrorCodeAuthentication = 1, + kFIRMessagingErrorCodeNoAccess = 2, + kFIRMessagingErrorCodeTimeout = 3, + kFIRMessagingErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRMessagingErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRMessagingErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRMessagingErrorCodeInvalidRequest = 7, + + // FIRMessaging generic errors + kFIRMessagingErrorCodeMissingDeviceID = 501, + + // upstream send errors + kFIRMessagingErrorServiceNotAvailable = 1001, + kFIRMessagingErrorInvalidParameters = 1002, + kFIRMessagingErrorMissingTo = 1003, + kFIRMessagingErrorSave = 1004, + kFIRMessagingErrorSizeExceeded = 1005, + // Future Send Errors + + // MCS errors + // Already connected with MCS + kFIRMessagingErrorCodeAlreadyConnected = 2001, + + // PubSub errors + kFIRMessagingErrorCodePubSubAlreadySubscribed = 3001, + kFIRMessagingErrorCodePubSubAlreadyUnsubscribed = 3002, + kFIRMessagingErrorCodePubSubInvalidTopic = 3003, + kFIRMessagingErrorCodePubSubFIRMessagingNotSetup = 3004, + kFIRMessagingErrorCodePubSubOperationIsCancelled = 3005, +}; + +@interface NSError (FIRMessaging) + +@property(nonatomic, readonly) FIRMessagingInternalErrorCode fcmErrorCode; + ++ (NSError *)errorWithFCMErrorCode:(FIRMessagingInternalErrorCode)fcmErrorCode; ++ (NSError *)fcm_errorWithCode:(NSInteger)code userInfo:(NSDictionary *)userInfo; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.m new file mode 100644 index 0000000..e4b8736 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/NSError+FIRMessaging.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRMessaging.h" + +NSString *const kFIRMessagingDomain = @"com.google.fcm"; + +@implementation NSError (FIRMessaging) + +- (FIRMessagingInternalErrorCode)fcmErrorCode { + return (FIRMessagingInternalErrorCode)self.code; +} + ++ (NSError *)errorWithFCMErrorCode:(FIRMessagingInternalErrorCode)fcmErrorCode { + return [NSError errorWithDomain:kFIRMessagingDomain code:fcmErrorCode userInfo:nil]; +} + ++ (NSError *)fcm_errorWithCode:(NSInteger)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRMessagingDomain code:code userInfo:userInfo]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.h new file mode 100644 index 0000000..46d2d9c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.h @@ -0,0 +1,1374 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_core.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GtalkAppData; +@class GtalkCellTower; +@class GtalkClientEvent; +@class GtalkErrorInfo; +@class GtalkExtension; +@class GtalkHeartbeatConfig; +@class GtalkHeartbeatStat; +@class GtalkPresenceStanza; +@class GtalkSetting; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GtalkLoginRequest_AuthService + +typedef GPB_ENUM(GtalkLoginRequest_AuthService) { + GtalkLoginRequest_AuthService_Mail = 0, + GtalkLoginRequest_AuthService_AndroidCloudToDeviceMessage = 1, + GtalkLoginRequest_AuthService_AndroidId = 2, +}; + +GPBEnumDescriptor *GtalkLoginRequest_AuthService_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkLoginRequest_AuthService_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkMessageStanza_MessageType + +typedef GPB_ENUM(GtalkMessageStanza_MessageType) { + GtalkMessageStanza_MessageType_Normal = 0, + GtalkMessageStanza_MessageType_Chat = 1, + GtalkMessageStanza_MessageType_Groupchat = 2, + GtalkMessageStanza_MessageType_Headline = 3, + GtalkMessageStanza_MessageType_Error = 4, +}; + +GPBEnumDescriptor *GtalkMessageStanza_MessageType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkMessageStanza_MessageType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_PresenceType + +typedef GPB_ENUM(GtalkPresenceStanza_PresenceType) { + GtalkPresenceStanza_PresenceType_Unavailable = 0, + GtalkPresenceStanza_PresenceType_Subscribe = 1, + GtalkPresenceStanza_PresenceType_Subscribed = 2, + GtalkPresenceStanza_PresenceType_Unsubscribe = 3, + GtalkPresenceStanza_PresenceType_Unsubscribed = 4, + GtalkPresenceStanza_PresenceType_Probe = 5, + GtalkPresenceStanza_PresenceType_Error = 6, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_PresenceType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_PresenceType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_ShowType + +typedef GPB_ENUM(GtalkPresenceStanza_ShowType) { + GtalkPresenceStanza_ShowType_Away = 0, + GtalkPresenceStanza_ShowType_Chat = 1, + GtalkPresenceStanza_ShowType_Dnd = 2, + GtalkPresenceStanza_ShowType_Xa = 3, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_ShowType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_ShowType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_ClientType + +typedef GPB_ENUM(GtalkPresenceStanza_ClientType) { + GtalkPresenceStanza_ClientType_Mobile = 0, + GtalkPresenceStanza_ClientType_Android = 1, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_ClientType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_ClientType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPresenceStanza_CapabilitiesFlags + +typedef GPB_ENUM(GtalkPresenceStanza_CapabilitiesFlags) { + GtalkPresenceStanza_CapabilitiesFlags_HasVoiceV1 = 1, + GtalkPresenceStanza_CapabilitiesFlags_HasVideoV1 = 2, + GtalkPresenceStanza_CapabilitiesFlags_HasCameraV1 = 4, + GtalkPresenceStanza_CapabilitiesFlags_HasPmucV1 = 8, +}; + +GPBEnumDescriptor *GtalkPresenceStanza_CapabilitiesFlags_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPresenceStanza_CapabilitiesFlags_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkBatchPresenceStanza_Type + +typedef GPB_ENUM(GtalkBatchPresenceStanza_Type) { + GtalkBatchPresenceStanza_Type_Get = 0, + GtalkBatchPresenceStanza_Type_Set = 1, +}; + +GPBEnumDescriptor *GtalkBatchPresenceStanza_Type_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkBatchPresenceStanza_Type_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkIqStanza_IqType + +typedef GPB_ENUM(GtalkIqStanza_IqType) { + GtalkIqStanza_IqType_Get = 0, + GtalkIqStanza_IqType_Set = 1, + GtalkIqStanza_IqType_Result = 2, + GtalkIqStanza_IqType_Error = 3, +}; + +GPBEnumDescriptor *GtalkIqStanza_IqType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkIqStanza_IqType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkClientEvent_Type + +typedef GPB_ENUM(GtalkClientEvent_Type) { + GtalkClientEvent_Type_Unknown = 0, + GtalkClientEvent_Type_DiscardedEvents = 1, + GtalkClientEvent_Type_FailedConnection = 2, + GtalkClientEvent_Type_SuccessfulConnection = 3, + GtalkClientEvent_Type_McsReconnectRequest = 4, + GtalkClientEvent_Type_FailedSocketCreationMcsReconnect = 5, + GtalkClientEvent_Type_McsReconnectLimited = 6, +}; + +GPBEnumDescriptor *GtalkClientEvent_Type_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkClientEvent_Type_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkClientEvent_McsReconnectAction + +typedef GPB_ENUM(GtalkClientEvent_McsReconnectAction) { + GtalkClientEvent_McsReconnectAction_None = 0, + GtalkClientEvent_McsReconnectAction_NotConnected = 1, + GtalkClientEvent_McsReconnectAction_TooSoon = 2, +}; + +GPBEnumDescriptor *GtalkClientEvent_McsReconnectAction_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkClientEvent_McsReconnectAction_IsValidValue(int32_t value); + +#pragma mark - GtalkGtalkCoreRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GtalkGtalkCoreRoot : GPBRootObject +@end + +#pragma mark - GtalkHeartbeatPing + +typedef GPB_ENUM(GtalkHeartbeatPing_FieldNumber) { + GtalkHeartbeatPing_FieldNumber_StreamId = 1, + GtalkHeartbeatPing_FieldNumber_LastStreamIdReceived = 2, + GtalkHeartbeatPing_FieldNumber_Status = 3, + GtalkHeartbeatPing_FieldNumber_CellTower = 4, + GtalkHeartbeatPing_FieldNumber_IntervalMs = 5, +}; + +@interface GtalkHeartbeatPing : GPBMessage + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkHeartbeatAck + +typedef GPB_ENUM(GtalkHeartbeatAck_FieldNumber) { + GtalkHeartbeatAck_FieldNumber_StreamId = 1, + GtalkHeartbeatAck_FieldNumber_LastStreamIdReceived = 2, + GtalkHeartbeatAck_FieldNumber_Status = 3, + GtalkHeartbeatAck_FieldNumber_CellTower = 4, + GtalkHeartbeatAck_FieldNumber_IntervalMs = 5, +}; + +@interface GtalkHeartbeatAck : GPBMessage + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkErrorInfo + +typedef GPB_ENUM(GtalkErrorInfo_FieldNumber) { + GtalkErrorInfo_FieldNumber_Code = 1, + GtalkErrorInfo_FieldNumber_Message = 2, + GtalkErrorInfo_FieldNumber_Type = 3, + GtalkErrorInfo_FieldNumber_Extension = 4, +}; + +@interface GtalkErrorInfo : GPBMessage + + +@property(nonatomic, readwrite) int32_t code; + +@property(nonatomic, readwrite) BOOL hasCode; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *message; +/** Test to see if @c message has been set. */ +@property(nonatomic, readwrite) BOOL hasMessage; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *type; +/** Test to see if @c type has been set. */ +@property(nonatomic, readwrite) BOOL hasType; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkExtension *extension; +/** Test to see if @c extension has been set. */ +@property(nonatomic, readwrite) BOOL hasExtension; + +@end + +#pragma mark - GtalkSetting + +typedef GPB_ENUM(GtalkSetting_FieldNumber) { + GtalkSetting_FieldNumber_Name = 1, + GtalkSetting_FieldNumber_Value = 2, +}; + +@interface GtalkSetting : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; +/** Test to see if @c name has been set. */ +@property(nonatomic, readwrite) BOOL hasName; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +#pragma mark - GtalkHeartbeatStat + +typedef GPB_ENUM(GtalkHeartbeatStat_FieldNumber) { + GtalkHeartbeatStat_FieldNumber_Ip = 1, + GtalkHeartbeatStat_FieldNumber_Timeout = 2, + GtalkHeartbeatStat_FieldNumber_IntervalMs = 3, +}; + +@interface GtalkHeartbeatStat : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ip; +/** Test to see if @c ip has been set. */ +@property(nonatomic, readwrite) BOOL hasIp; + + +@property(nonatomic, readwrite) BOOL timeout; + +@property(nonatomic, readwrite) BOOL hasTimeout; + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkHeartbeatConfig + +typedef GPB_ENUM(GtalkHeartbeatConfig_FieldNumber) { + GtalkHeartbeatConfig_FieldNumber_UploadStat = 1, + GtalkHeartbeatConfig_FieldNumber_Ip = 2, + GtalkHeartbeatConfig_FieldNumber_IntervalMs = 3, +}; + +@interface GtalkHeartbeatConfig : GPBMessage + + +@property(nonatomic, readwrite) BOOL uploadStat; + +@property(nonatomic, readwrite) BOOL hasUploadStat; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ip; +/** Test to see if @c ip has been set. */ +@property(nonatomic, readwrite) BOOL hasIp; + + +@property(nonatomic, readwrite) int32_t intervalMs; + +@property(nonatomic, readwrite) BOOL hasIntervalMs; +@end + +#pragma mark - GtalkLoginRequest + +typedef GPB_ENUM(GtalkLoginRequest_FieldNumber) { + GtalkLoginRequest_FieldNumber_Id_p = 1, + GtalkLoginRequest_FieldNumber_Domain = 2, + GtalkLoginRequest_FieldNumber_User = 3, + GtalkLoginRequest_FieldNumber_Resource = 4, + GtalkLoginRequest_FieldNumber_AuthToken = 5, + GtalkLoginRequest_FieldNumber_DeviceId = 6, + GtalkLoginRequest_FieldNumber_LastRmqId = 7, + GtalkLoginRequest_FieldNumber_SettingArray = 8, + GtalkLoginRequest_FieldNumber_ReceivedPersistentIdArray = 10, + GtalkLoginRequest_FieldNumber_IncludeStreamIds = 11, + GtalkLoginRequest_FieldNumber_HeartbeatStat = 13, + GtalkLoginRequest_FieldNumber_UseRmq2 = 14, + GtalkLoginRequest_FieldNumber_AccountId = 15, + GtalkLoginRequest_FieldNumber_AuthService = 16, + GtalkLoginRequest_FieldNumber_NetworkType = 17, + GtalkLoginRequest_FieldNumber_Status = 18, + GtalkLoginRequest_FieldNumber_TokenVersionInfo = 19, + GtalkLoginRequest_FieldNumber_CellTower = 20, + GtalkLoginRequest_FieldNumber_GcmStartTimeMs = 21, + GtalkLoginRequest_FieldNumber_ClientEventArray = 22, + GtalkLoginRequest_FieldNumber_OnFallback = 23, + GtalkLoginRequest_FieldNumber_NoPendingUpstream = 24, + GtalkLoginRequest_FieldNumber_ReconnectRequestId = 25, +}; + +@interface GtalkLoginRequest : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *domain; +/** Test to see if @c domain has been set. */ +@property(nonatomic, readwrite) BOOL hasDomain; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *resource; +/** Test to see if @c resource has been set. */ +@property(nonatomic, readwrite) BOOL hasResource; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *authToken; +/** Test to see if @c authToken has been set. */ +@property(nonatomic, readwrite) BOOL hasAuthToken; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *deviceId; +/** Test to see if @c deviceId has been set. */ +@property(nonatomic, readwrite) BOOL hasDeviceId; + + +@property(nonatomic, readwrite) int64_t lastRmqId; + +@property(nonatomic, readwrite) BOOL hasLastRmqId; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *settingArray; +/** The number of items in @c settingArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger settingArray_Count; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *receivedPersistentIdArray; +/** The number of items in @c receivedPersistentIdArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger receivedPersistentIdArray_Count; + + +@property(nonatomic, readwrite) BOOL includeStreamIds; + +@property(nonatomic, readwrite) BOOL hasIncludeStreamIds; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkHeartbeatStat *heartbeatStat; +/** Test to see if @c heartbeatStat has been set. */ +@property(nonatomic, readwrite) BOOL hasHeartbeatStat; + + +@property(nonatomic, readwrite) BOOL useRmq2; + +@property(nonatomic, readwrite) BOOL hasUseRmq2; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; + +@property(nonatomic, readwrite) GtalkLoginRequest_AuthService authService; + +@property(nonatomic, readwrite) BOOL hasAuthService; + +@property(nonatomic, readwrite) int32_t networkType; + +@property(nonatomic, readwrite) BOOL hasNetworkType; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *tokenVersionInfo; +/** Test to see if @c tokenVersionInfo has been set. */ +@property(nonatomic, readwrite) BOOL hasTokenVersionInfo; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) uint64_t gcmStartTimeMs; + +@property(nonatomic, readwrite) BOOL hasGcmStartTimeMs; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *clientEventArray; +/** The number of items in @c clientEventArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger clientEventArray_Count; + + +@property(nonatomic, readwrite) BOOL onFallback; + +@property(nonatomic, readwrite) BOOL hasOnFallback; + +@property(nonatomic, readwrite) BOOL noPendingUpstream; + +@property(nonatomic, readwrite) BOOL hasNoPendingUpstream; + +@property(nonatomic, readwrite) int32_t reconnectRequestId; + +@property(nonatomic, readwrite) BOOL hasReconnectRequestId; +@end + +#pragma mark - GtalkLoginResponse + +typedef GPB_ENUM(GtalkLoginResponse_FieldNumber) { + GtalkLoginResponse_FieldNumber_Id_p = 1, + GtalkLoginResponse_FieldNumber_Jid = 2, + GtalkLoginResponse_FieldNumber_Error = 3, + GtalkLoginResponse_FieldNumber_SettingArray = 4, + GtalkLoginResponse_FieldNumber_StreamId = 5, + GtalkLoginResponse_FieldNumber_LastStreamIdReceived = 6, + GtalkLoginResponse_FieldNumber_HeartbeatConfig = 7, + GtalkLoginResponse_FieldNumber_ServerTimestamp = 8, +}; + +@interface GtalkLoginResponse : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *settingArray; +/** The number of items in @c settingArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger settingArray_Count; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkHeartbeatConfig *heartbeatConfig; +/** Test to see if @c heartbeatConfig has been set. */ +@property(nonatomic, readwrite) BOOL hasHeartbeatConfig; + + +@property(nonatomic, readwrite) int64_t serverTimestamp; + +@property(nonatomic, readwrite) BOOL hasServerTimestamp; +@end + +#pragma mark - GtalkBindAccountRequest + +typedef GPB_ENUM(GtalkBindAccountRequest_FieldNumber) { + GtalkBindAccountRequest_FieldNumber_Id_p = 1, + GtalkBindAccountRequest_FieldNumber_Domain = 2, + GtalkBindAccountRequest_FieldNumber_User = 3, + GtalkBindAccountRequest_FieldNumber_Resource = 4, + GtalkBindAccountRequest_FieldNumber_AuthToken = 5, + GtalkBindAccountRequest_FieldNumber_PersistentId = 6, + GtalkBindAccountRequest_FieldNumber_StreamId = 7, + GtalkBindAccountRequest_FieldNumber_LastStreamIdReceived = 8, + GtalkBindAccountRequest_FieldNumber_AccountId = 9, +}; + +@interface GtalkBindAccountRequest : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *domain; +/** Test to see if @c domain has been set. */ +@property(nonatomic, readwrite) BOOL hasDomain; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *resource; +/** Test to see if @c resource has been set. */ +@property(nonatomic, readwrite) BOOL hasResource; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *authToken; +/** Test to see if @c authToken has been set. */ +@property(nonatomic, readwrite) BOOL hasAuthToken; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; +@end + +#pragma mark - GtalkBindAccountResponse + +typedef GPB_ENUM(GtalkBindAccountResponse_FieldNumber) { + GtalkBindAccountResponse_FieldNumber_Id_p = 1, + GtalkBindAccountResponse_FieldNumber_Jid = 2, + GtalkBindAccountResponse_FieldNumber_Error = 3, + GtalkBindAccountResponse_FieldNumber_StreamId = 4, + GtalkBindAccountResponse_FieldNumber_LastStreamIdReceived = 5, +}; + +@interface GtalkBindAccountResponse : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; +@end + +#pragma mark - GtalkStreamErrorStanza + +typedef GPB_ENUM(GtalkStreamErrorStanza_FieldNumber) { + GtalkStreamErrorStanza_FieldNumber_Type = 1, + GtalkStreamErrorStanza_FieldNumber_Text = 2, +}; + +@interface GtalkStreamErrorStanza : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *type; +/** Test to see if @c type has been set. */ +@property(nonatomic, readwrite) BOOL hasType; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *text; +/** Test to see if @c text has been set. */ +@property(nonatomic, readwrite) BOOL hasText; + +@end + +#pragma mark - GtalkClose + +@interface GtalkClose : GPBMessage + +@end + +#pragma mark - GtalkExtension + +typedef GPB_ENUM(GtalkExtension_FieldNumber) { + GtalkExtension_FieldNumber_Id_p = 1, + GtalkExtension_FieldNumber_Data_p = 2, +}; + +@interface GtalkExtension : GPBMessage + + +@property(nonatomic, readwrite) int32_t id_p; + +@property(nonatomic, readwrite) BOOL hasId_p; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *data_p; +/** Test to see if @c data_p has been set. */ +@property(nonatomic, readwrite) BOOL hasData_p; + +@end + +#pragma mark - GtalkMessageStanza + +typedef GPB_ENUM(GtalkMessageStanza_FieldNumber) { + GtalkMessageStanza_FieldNumber_RmqId = 1, + GtalkMessageStanza_FieldNumber_Type = 2, + GtalkMessageStanza_FieldNumber_Id_p = 3, + GtalkMessageStanza_FieldNumber_From = 4, + GtalkMessageStanza_FieldNumber_To = 5, + GtalkMessageStanza_FieldNumber_Subject = 6, + GtalkMessageStanza_FieldNumber_Body = 7, + GtalkMessageStanza_FieldNumber_Thread = 8, + GtalkMessageStanza_FieldNumber_Error = 9, + GtalkMessageStanza_FieldNumber_ExtensionArray = 10, + GtalkMessageStanza_FieldNumber_Nosave = 11, + GtalkMessageStanza_FieldNumber_Timestamp = 12, + GtalkMessageStanza_FieldNumber_PersistentId = 13, + GtalkMessageStanza_FieldNumber_StreamId = 14, + GtalkMessageStanza_FieldNumber_LastStreamIdReceived = 15, + GtalkMessageStanza_FieldNumber_Read = 16, + GtalkMessageStanza_FieldNumber_AccountId = 17, +}; + +@interface GtalkMessageStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite) GtalkMessageStanza_MessageType type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *subject; +/** Test to see if @c subject has been set. */ +@property(nonatomic, readwrite) BOOL hasSubject; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *body; +/** Test to see if @c body has been set. */ +@property(nonatomic, readwrite) BOOL hasBody; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *thread; +/** Test to see if @c thread has been set. */ +@property(nonatomic, readwrite) BOOL hasThread; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray; +/** The number of items in @c extensionArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger extensionArray_Count; + + +@property(nonatomic, readwrite) BOOL nosave; + +@property(nonatomic, readwrite) BOOL hasNosave; + +@property(nonatomic, readwrite) int64_t timestamp; + +@property(nonatomic, readwrite) BOOL hasTimestamp; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL read; + +@property(nonatomic, readwrite) BOOL hasRead; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; +@end + +#pragma mark - GtalkPresenceStanza + +typedef GPB_ENUM(GtalkPresenceStanza_FieldNumber) { + GtalkPresenceStanza_FieldNumber_RmqId = 1, + GtalkPresenceStanza_FieldNumber_Type = 2, + GtalkPresenceStanza_FieldNumber_Id_p = 3, + GtalkPresenceStanza_FieldNumber_From = 4, + GtalkPresenceStanza_FieldNumber_To = 5, + GtalkPresenceStanza_FieldNumber_Show = 6, + GtalkPresenceStanza_FieldNumber_Status = 7, + GtalkPresenceStanza_FieldNumber_Priority = 8, + GtalkPresenceStanza_FieldNumber_Error = 9, + GtalkPresenceStanza_FieldNumber_ExtensionArray = 10, + GtalkPresenceStanza_FieldNumber_Client = 11, + GtalkPresenceStanza_FieldNumber_AvatarHash = 12, + GtalkPresenceStanza_FieldNumber_PersistentId = 13, + GtalkPresenceStanza_FieldNumber_StreamId = 14, + GtalkPresenceStanza_FieldNumber_LastStreamIdReceived = 15, + GtalkPresenceStanza_FieldNumber_CapabilitiesFlags = 16, + GtalkPresenceStanza_FieldNumber_AccountId = 17, +}; + +@interface GtalkPresenceStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite) GtalkPresenceStanza_PresenceType type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite) GtalkPresenceStanza_ShowType show; + +@property(nonatomic, readwrite) BOOL hasShow; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *status; +/** Test to see if @c status has been set. */ +@property(nonatomic, readwrite) BOOL hasStatus; + + +@property(nonatomic, readwrite) int32_t priority; + +@property(nonatomic, readwrite) BOOL hasPriority; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray; +/** The number of items in @c extensionArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger extensionArray_Count; + + +@property(nonatomic, readwrite) GtalkPresenceStanza_ClientType client; + +@property(nonatomic, readwrite) BOOL hasClient; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *avatarHash; +/** Test to see if @c avatarHash has been set. */ +@property(nonatomic, readwrite) BOOL hasAvatarHash; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int32_t capabilitiesFlags; + +@property(nonatomic, readwrite) BOOL hasCapabilitiesFlags; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; +@end + +#pragma mark - GtalkBatchPresenceStanza + +typedef GPB_ENUM(GtalkBatchPresenceStanza_FieldNumber) { + GtalkBatchPresenceStanza_FieldNumber_Id_p = 1, + GtalkBatchPresenceStanza_FieldNumber_To = 2, + GtalkBatchPresenceStanza_FieldNumber_PresenceArray = 3, + GtalkBatchPresenceStanza_FieldNumber_PersistentId = 4, + GtalkBatchPresenceStanza_FieldNumber_StreamId = 5, + GtalkBatchPresenceStanza_FieldNumber_LastStreamIdReceived = 6, + GtalkBatchPresenceStanza_FieldNumber_AccountId = 7, + GtalkBatchPresenceStanza_FieldNumber_Type = 8, + GtalkBatchPresenceStanza_FieldNumber_Error = 9, +}; + +@interface GtalkBatchPresenceStanza : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *presenceArray; +/** The number of items in @c presenceArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger presenceArray_Count; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; + +@property(nonatomic, readwrite) GtalkBatchPresenceStanza_Type type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + +@end + +#pragma mark - GtalkIqStanza + +typedef GPB_ENUM(GtalkIqStanza_FieldNumber) { + GtalkIqStanza_FieldNumber_RmqId = 1, + GtalkIqStanza_FieldNumber_Type = 2, + GtalkIqStanza_FieldNumber_Id_p = 3, + GtalkIqStanza_FieldNumber_From = 4, + GtalkIqStanza_FieldNumber_To = 5, + GtalkIqStanza_FieldNumber_Error = 6, + GtalkIqStanza_FieldNumber_Extension = 7, + GtalkIqStanza_FieldNumber_PersistentId = 8, + GtalkIqStanza_FieldNumber_StreamId = 9, + GtalkIqStanza_FieldNumber_LastStreamIdReceived = 10, + GtalkIqStanza_FieldNumber_AccountId = 11, + GtalkIqStanza_FieldNumber_Status = 12, +}; + +@interface GtalkIqStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite) GtalkIqStanza_IqType type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkErrorInfo *error; +/** Test to see if @c error has been set. */ +@property(nonatomic, readwrite) BOOL hasError; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkExtension *extension; +/** Test to see if @c extension has been set. */ +@property(nonatomic, readwrite) BOOL hasExtension; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite) int64_t accountId; + +@property(nonatomic, readwrite) BOOL hasAccountId; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; +@end + +#pragma mark - GtalkAppData + +typedef GPB_ENUM(GtalkAppData_FieldNumber) { + GtalkAppData_FieldNumber_Key = 1, + GtalkAppData_FieldNumber_Value = 2, +}; + +@interface GtalkAppData : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *key; +/** Test to see if @c key has been set. */ +@property(nonatomic, readwrite) BOOL hasKey; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +#pragma mark - GtalkDataMessageStanza + +typedef GPB_ENUM(GtalkDataMessageStanza_FieldNumber) { + GtalkDataMessageStanza_FieldNumber_RmqId = 1, + GtalkDataMessageStanza_FieldNumber_Id_p = 2, + GtalkDataMessageStanza_FieldNumber_From = 3, + GtalkDataMessageStanza_FieldNumber_To = 4, + GtalkDataMessageStanza_FieldNumber_Category = 5, + GtalkDataMessageStanza_FieldNumber_Token = 6, + GtalkDataMessageStanza_FieldNumber_AppDataArray = 7, + GtalkDataMessageStanza_FieldNumber_FromTrustedServer = 8, + GtalkDataMessageStanza_FieldNumber_PersistentId = 9, + GtalkDataMessageStanza_FieldNumber_StreamId = 10, + GtalkDataMessageStanza_FieldNumber_LastStreamIdReceived = 11, + GtalkDataMessageStanza_FieldNumber_Permission = 12, + GtalkDataMessageStanza_FieldNumber_RegId = 13, + GtalkDataMessageStanza_FieldNumber_PkgSignature = 14, + GtalkDataMessageStanza_FieldNumber_ClientId = 15, + GtalkDataMessageStanza_FieldNumber_DeviceUserId = 16, + GtalkDataMessageStanza_FieldNumber_Ttl = 17, + GtalkDataMessageStanza_FieldNumber_Sent = 18, + GtalkDataMessageStanza_FieldNumber_Queued = 19, + GtalkDataMessageStanza_FieldNumber_Status = 20, + GtalkDataMessageStanza_FieldNumber_RawData = 21, + GtalkDataMessageStanza_FieldNumber_MaxDelay = 22, + GtalkDataMessageStanza_FieldNumber_ActualDelay = 23, + GtalkDataMessageStanza_FieldNumber_ImmediateAck = 24, + GtalkDataMessageStanza_FieldNumber_DeliveryReceiptRequested = 25, + GtalkDataMessageStanza_FieldNumber_ExternalMessageId = 26, + GtalkDataMessageStanza_FieldNumber_Flags = 27, + GtalkDataMessageStanza_FieldNumber_CellTower = 28, + GtalkDataMessageStanza_FieldNumber_Priority = 29, +}; + +@interface GtalkDataMessageStanza : GPBMessage + + +@property(nonatomic, readwrite) int64_t rmqId; + +@property(nonatomic, readwrite) BOOL hasRmqId; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *from; +/** Test to see if @c from has been set. */ +@property(nonatomic, readwrite) BOOL hasFrom; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *to; +/** Test to see if @c to has been set. */ +@property(nonatomic, readwrite) BOOL hasTo; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *category; +/** Test to see if @c category has been set. */ +@property(nonatomic, readwrite) BOOL hasCategory; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *token; +/** Test to see if @c token has been set. */ +@property(nonatomic, readwrite) BOOL hasToken; + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *appDataArray; +/** The number of items in @c appDataArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger appDataArray_Count; + + +@property(nonatomic, readwrite) BOOL fromTrustedServer; + +@property(nonatomic, readwrite) BOOL hasFromTrustedServer; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *persistentId; +/** Test to see if @c persistentId has been set. */ +@property(nonatomic, readwrite) BOOL hasPersistentId; + + +@property(nonatomic, readwrite) int32_t streamId; + +@property(nonatomic, readwrite) BOOL hasStreamId; + +@property(nonatomic, readwrite) int32_t lastStreamIdReceived; + +@property(nonatomic, readwrite) BOOL hasLastStreamIdReceived; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *permission; +/** Test to see if @c permission has been set. */ +@property(nonatomic, readwrite) BOOL hasPermission; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *regId; +/** Test to see if @c regId has been set. */ +@property(nonatomic, readwrite) BOOL hasRegId; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *pkgSignature; +/** Test to see if @c pkgSignature has been set. */ +@property(nonatomic, readwrite) BOOL hasPkgSignature; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *clientId; +/** Test to see if @c clientId has been set. */ +@property(nonatomic, readwrite) BOOL hasClientId; + + +@property(nonatomic, readwrite) int64_t deviceUserId; + +@property(nonatomic, readwrite) BOOL hasDeviceUserId; + +@property(nonatomic, readwrite) int32_t ttl; + +@property(nonatomic, readwrite) BOOL hasTtl; + +@property(nonatomic, readwrite) int64_t sent; + +@property(nonatomic, readwrite) BOOL hasSent; + +@property(nonatomic, readwrite) int32_t queued; + +@property(nonatomic, readwrite) BOOL hasQueued; + +@property(nonatomic, readwrite) int64_t status; + +@property(nonatomic, readwrite) BOOL hasStatus; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *rawData; +/** Test to see if @c rawData has been set. */ +@property(nonatomic, readwrite) BOOL hasRawData; + + +@property(nonatomic, readwrite) int32_t maxDelay; + +@property(nonatomic, readwrite) BOOL hasMaxDelay; + +@property(nonatomic, readwrite) int32_t actualDelay; + +@property(nonatomic, readwrite) BOOL hasActualDelay; + +@property(nonatomic, readwrite) BOOL immediateAck; + +@property(nonatomic, readwrite) BOOL hasImmediateAck; + +@property(nonatomic, readwrite) BOOL deliveryReceiptRequested; + +@property(nonatomic, readwrite) BOOL hasDeliveryReceiptRequested; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *externalMessageId; +/** Test to see if @c externalMessageId has been set. */ +@property(nonatomic, readwrite) BOOL hasExternalMessageId; + + +@property(nonatomic, readwrite) int64_t flags; + +@property(nonatomic, readwrite) BOOL hasFlags; + +@property(nonatomic, readwrite, strong, null_resettable) GtalkCellTower *cellTower DEPRECATED_ATTRIBUTE; +/** Test to see if @c cellTower has been set. */ +@property(nonatomic, readwrite) BOOL hasCellTower DEPRECATED_ATTRIBUTE; + + +@property(nonatomic, readwrite) int32_t priority; + +@property(nonatomic, readwrite) BOOL hasPriority; +@end + +#pragma mark - GtalkTalkMetadata + +typedef GPB_ENUM(GtalkTalkMetadata_FieldNumber) { + GtalkTalkMetadata_FieldNumber_Foreground = 1, +}; + +@interface GtalkTalkMetadata : GPBMessage + + +@property(nonatomic, readwrite) BOOL foreground; + +@property(nonatomic, readwrite) BOOL hasForeground; +@end + +#pragma mark - GtalkCellTower + +typedef GPB_ENUM(GtalkCellTower_FieldNumber) { + GtalkCellTower_FieldNumber_Id_p = 1, + GtalkCellTower_FieldNumber_KnownCongestionStatus = 2, +}; + +DEPRECATED_ATTRIBUTE +@interface GtalkCellTower : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *id_p; +/** Test to see if @c id_p has been set. */ +@property(nonatomic, readwrite) BOOL hasId_p; + + +@property(nonatomic, readwrite) int32_t knownCongestionStatus; + +@property(nonatomic, readwrite) BOOL hasKnownCongestionStatus; +@end + +#pragma mark - GtalkClientEvent + +typedef GPB_ENUM(GtalkClientEvent_FieldNumber) { + GtalkClientEvent_FieldNumber_Type = 1, + GtalkClientEvent_FieldNumber_NumberDiscardedEvents = 100, + GtalkClientEvent_FieldNumber_NetworkType = 200, + GtalkClientEvent_FieldNumber_NetworkPort = 201, + GtalkClientEvent_FieldNumber_TimeConnectionStartedMs = 202, + GtalkClientEvent_FieldNumber_TimeConnectionEndedMs = 203, + GtalkClientEvent_FieldNumber_ErrorCode = 204, + GtalkClientEvent_FieldNumber_TimeConnectionEstablishedMs = 300, + GtalkClientEvent_FieldNumber_McsReconnectAction = 400, +}; + +@interface GtalkClientEvent : GPBMessage + + +@property(nonatomic, readwrite) GtalkClientEvent_Type type; + +@property(nonatomic, readwrite) BOOL hasType; + +@property(nonatomic, readwrite) uint32_t numberDiscardedEvents; + +@property(nonatomic, readwrite) BOOL hasNumberDiscardedEvents; + +@property(nonatomic, readwrite) int32_t networkType; + +@property(nonatomic, readwrite) BOOL hasNetworkType; + +@property(nonatomic, readwrite) int32_t networkPort; + +@property(nonatomic, readwrite) BOOL hasNetworkPort; + +@property(nonatomic, readwrite) uint64_t timeConnectionStartedMs; + +@property(nonatomic, readwrite) BOOL hasTimeConnectionStartedMs; + +@property(nonatomic, readwrite) uint64_t timeConnectionEndedMs; + +@property(nonatomic, readwrite) BOOL hasTimeConnectionEndedMs; + +@property(nonatomic, readwrite) int32_t errorCode; + +@property(nonatomic, readwrite) BOOL hasErrorCode; + +@property(nonatomic, readwrite) uint64_t timeConnectionEstablishedMs; + +@property(nonatomic, readwrite) BOOL hasTimeConnectionEstablishedMs; + +@property(nonatomic, readwrite) GtalkClientEvent_McsReconnectAction mcsReconnectAction; + +@property(nonatomic, readwrite) BOOL hasMcsReconnectAction; +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.m new file mode 100644 index 0000000..06c9134 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkCore.pbobjc.m @@ -0,0 +1,3017 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_core.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + + #import "GtalkCore.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GtalkGtalkCoreRoot + +@implementation GtalkGtalkCoreRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GtalkGtalkCoreRoot_FileDescriptor + +static GPBFileDescriptor *GtalkGtalkCoreRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"mobilegtalk" + objcPrefix:@"Gtalk" + syntax:GPBFileSyntaxProto2]; + } + return descriptor; +} + +#pragma mark - GtalkHeartbeatPing + +@implementation GtalkHeartbeatPing + +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasStatus, status; +@dynamic hasCellTower, cellTower; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatPing__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t intervalMs; + GtalkCellTower *cellTower; + int64_t status; +} GtalkHeartbeatPing__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_StreamId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_LastStreamIdReceived, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_Status, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkHeartbeatPing_FieldNumber_CellTower, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatPing_FieldNumber_IntervalMs, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkHeartbeatPing__storage_, intervalMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatPing class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatPing__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkHeartbeatAck + +@implementation GtalkHeartbeatAck + +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasStatus, status; +@dynamic hasCellTower, cellTower; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatAck__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t intervalMs; + GtalkCellTower *cellTower; + int64_t status; +} GtalkHeartbeatAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_StreamId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_LastStreamIdReceived, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_Status, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkHeartbeatAck_FieldNumber_CellTower, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatAck_FieldNumber_IntervalMs, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkHeartbeatAck__storage_, intervalMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatAck class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkErrorInfo + +@implementation GtalkErrorInfo + +@dynamic hasCode, code; +@dynamic hasMessage, message; +@dynamic hasType, type; +@dynamic hasExtension, extension; + +typedef struct GtalkErrorInfo__storage_ { + uint32_t _has_storage_[1]; + int32_t code; + NSString *message; + NSString *type; + GtalkExtension *extension; +} GtalkErrorInfo__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "code", + .dataTypeSpecific.className = NULL, + .number = GtalkErrorInfo_FieldNumber_Code, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, code), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt32, + }, + { + .name = "message", + .dataTypeSpecific.className = NULL, + .number = GtalkErrorInfo_FieldNumber_Message, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, message), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "type", + .dataTypeSpecific.className = NULL, + .number = GtalkErrorInfo_FieldNumber_Type, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, type), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "extension", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkErrorInfo_FieldNumber_Extension, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkErrorInfo__storage_, extension), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkErrorInfo class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkErrorInfo__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkSetting + +@implementation GtalkSetting + +@dynamic hasName, name; +@dynamic hasValue, value; + +typedef struct GtalkSetting__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + NSString *value; +} GtalkSetting__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GtalkSetting_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkSetting__storage_, name), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GtalkSetting_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkSetting__storage_, value), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSetting class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSetting__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkHeartbeatStat + +@implementation GtalkHeartbeatStat + +@dynamic hasIp, ip; +@dynamic hasTimeout, timeout; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatStat__storage_ { + uint32_t _has_storage_[1]; + int32_t intervalMs; + NSString *ip; +} GtalkHeartbeatStat__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "ip", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatStat_FieldNumber_Ip, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkHeartbeatStat__storage_, ip), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "timeout", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatStat_FieldNumber_Timeout, + .hasIndex = 1, + .offset = 2, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatStat_FieldNumber_IntervalMs, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatStat__storage_, intervalMs), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatStat class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatStat__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkHeartbeatConfig + +@implementation GtalkHeartbeatConfig + +@dynamic hasUploadStat, uploadStat; +@dynamic hasIp, ip; +@dynamic hasIntervalMs, intervalMs; + +typedef struct GtalkHeartbeatConfig__storage_ { + uint32_t _has_storage_[1]; + int32_t intervalMs; + NSString *ip; +} GtalkHeartbeatConfig__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "uploadStat", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatConfig_FieldNumber_UploadStat, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "ip", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatConfig_FieldNumber_Ip, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkHeartbeatConfig__storage_, ip), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "intervalMs", + .dataTypeSpecific.className = NULL, + .number = GtalkHeartbeatConfig_FieldNumber_IntervalMs, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkHeartbeatConfig__storage_, intervalMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkHeartbeatConfig class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkHeartbeatConfig__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkLoginRequest + +@implementation GtalkLoginRequest + +@dynamic hasId_p, id_p; +@dynamic hasDomain, domain; +@dynamic hasUser, user; +@dynamic hasResource, resource; +@dynamic hasAuthToken, authToken; +@dynamic hasDeviceId, deviceId; +@dynamic hasLastRmqId, lastRmqId; +@dynamic settingArray, settingArray_Count; +@dynamic receivedPersistentIdArray, receivedPersistentIdArray_Count; +@dynamic hasIncludeStreamIds, includeStreamIds; +@dynamic hasHeartbeatStat, heartbeatStat; +@dynamic hasUseRmq2, useRmq2; +@dynamic hasAccountId, accountId; +@dynamic hasAuthService, authService; +@dynamic hasNetworkType, networkType; +@dynamic hasStatus, status; +@dynamic hasTokenVersionInfo, tokenVersionInfo; +@dynamic hasCellTower, cellTower; +@dynamic hasGcmStartTimeMs, gcmStartTimeMs; +@dynamic clientEventArray, clientEventArray_Count; +@dynamic hasOnFallback, onFallback; +@dynamic hasNoPendingUpstream, noPendingUpstream; +@dynamic hasReconnectRequestId, reconnectRequestId; + +typedef struct GtalkLoginRequest__storage_ { + uint32_t _has_storage_[1]; + GtalkLoginRequest_AuthService authService; + int32_t networkType; + int32_t reconnectRequestId; + NSString *id_p; + NSString *domain; + NSString *user; + NSString *resource; + NSString *authToken; + NSString *deviceId; + NSMutableArray *settingArray; + NSMutableArray *receivedPersistentIdArray; + GtalkHeartbeatStat *heartbeatStat; + NSString *tokenVersionInfo; + GtalkCellTower *cellTower; + NSMutableArray *clientEventArray; + int64_t lastRmqId; + int64_t accountId; + int64_t status; + uint64_t gcmStartTimeMs; +} GtalkLoginRequest__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "domain", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Domain, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, domain), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_User, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "resource", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Resource, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, resource), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "authToken", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_AuthToken, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, authToken), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "deviceId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_DeviceId, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, deviceId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "lastRmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_LastRmqId, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, lastRmqId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "settingArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkSetting), + .number = GtalkLoginRequest_FieldNumber_SettingArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, settingArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "receivedPersistentIdArray", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_ReceivedPersistentIdArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, receivedPersistentIdArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "includeStreamIds", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_IncludeStreamIds, + .hasIndex = 7, + .offset = 8, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "heartbeatStat", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkHeartbeatStat), + .number = GtalkLoginRequest_FieldNumber_HeartbeatStat, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, heartbeatStat), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "useRmq2", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_UseRmq2, + .hasIndex = 10, + .offset = 11, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_AccountId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "authService", + .dataTypeSpecific.enumDescFunc = GtalkLoginRequest_AuthService_EnumDescriptor, + .number = GtalkLoginRequest_FieldNumber_AuthService, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, authService), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "networkType", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_NetworkType, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, networkType), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_Status, + .hasIndex = 15, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "tokenVersionInfo", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_TokenVersionInfo, + .hasIndex = 16, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, tokenVersionInfo), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkLoginRequest_FieldNumber_CellTower, + .hasIndex = 17, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "gcmStartTimeMs", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_GcmStartTimeMs, + .hasIndex = 18, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, gcmStartTimeMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "clientEventArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkClientEvent), + .number = GtalkLoginRequest_FieldNumber_ClientEventArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, clientEventArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "onFallback", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_OnFallback, + .hasIndex = 19, + .offset = 20, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "noPendingUpstream", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_NoPendingUpstream, + .hasIndex = 21, + .offset = 22, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "reconnectRequestId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginRequest_FieldNumber_ReconnectRequestId, + .hasIndex = 23, + .offset = (uint32_t)offsetof(GtalkLoginRequest__storage_, reconnectRequestId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkLoginRequest class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkLoginRequest__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkLoginRequest_AuthService + +GPBEnumDescriptor *GtalkLoginRequest_AuthService_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Mail\000AndroidCloudToDeviceMessage\000Android" + "Id\000"; + static const int32_t values[] = { + GtalkLoginRequest_AuthService_Mail, + GtalkLoginRequest_AuthService_AndroidCloudToDeviceMessage, + GtalkLoginRequest_AuthService_AndroidId, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkLoginRequest_AuthService) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkLoginRequest_AuthService_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkLoginRequest_AuthService_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkLoginRequest_AuthService_Mail: + case GtalkLoginRequest_AuthService_AndroidCloudToDeviceMessage: + case GtalkLoginRequest_AuthService_AndroidId: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkLoginResponse + +@implementation GtalkLoginResponse + +@dynamic hasId_p, id_p; +@dynamic hasJid, jid; +@dynamic hasError, error; +@dynamic settingArray, settingArray_Count; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasHeartbeatConfig, heartbeatConfig; +@dynamic hasServerTimestamp, serverTimestamp; + +typedef struct GtalkLoginResponse__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *jid; + GtalkErrorInfo *error; + NSMutableArray *settingArray; + GtalkHeartbeatConfig *heartbeatConfig; + int64_t serverTimestamp; +} GtalkLoginResponse__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_Jid, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, jid), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkLoginResponse_FieldNumber_Error, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "settingArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkSetting), + .number = GtalkLoginResponse_FieldNumber_SettingArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, settingArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_StreamId, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_LastStreamIdReceived, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "heartbeatConfig", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkHeartbeatConfig), + .number = GtalkLoginResponse_FieldNumber_HeartbeatConfig, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, heartbeatConfig), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "serverTimestamp", + .dataTypeSpecific.className = NULL, + .number = GtalkLoginResponse_FieldNumber_ServerTimestamp, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkLoginResponse__storage_, serverTimestamp), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkLoginResponse class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkLoginResponse__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkBindAccountRequest + +@implementation GtalkBindAccountRequest + +@dynamic hasId_p, id_p; +@dynamic hasDomain, domain; +@dynamic hasUser, user; +@dynamic hasResource, resource; +@dynamic hasAuthToken, authToken; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasAccountId, accountId; + +typedef struct GtalkBindAccountRequest__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *domain; + NSString *user; + NSString *resource; + NSString *authToken; + NSString *persistentId; + int64_t accountId; +} GtalkBindAccountRequest__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "domain", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_Domain, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, domain), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_User, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "resource", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_Resource, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, resource), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "authToken", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_AuthToken, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, authToken), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_PersistentId, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_StreamId, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_LastStreamIdReceived, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountRequest_FieldNumber_AccountId, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkBindAccountRequest__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkBindAccountRequest class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkBindAccountRequest__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkBindAccountResponse + +@implementation GtalkBindAccountResponse + +@dynamic hasId_p, id_p; +@dynamic hasJid, jid; +@dynamic hasError, error; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; + +typedef struct GtalkBindAccountResponse__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *jid; + GtalkErrorInfo *error; +} GtalkBindAccountResponse__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_Jid, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, jid), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkBindAccountResponse_FieldNumber_Error, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_StreamId, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkBindAccountResponse_FieldNumber_LastStreamIdReceived, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkBindAccountResponse__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkBindAccountResponse class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkBindAccountResponse__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkStreamErrorStanza + +@implementation GtalkStreamErrorStanza + +@dynamic hasType, type; +@dynamic hasText, text; + +typedef struct GtalkStreamErrorStanza__storage_ { + uint32_t _has_storage_[1]; + NSString *type; + NSString *text; +} GtalkStreamErrorStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "type", + .dataTypeSpecific.className = NULL, + .number = GtalkStreamErrorStanza_FieldNumber_Type, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkStreamErrorStanza__storage_, type), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "text", + .dataTypeSpecific.className = NULL, + .number = GtalkStreamErrorStanza_FieldNumber_Text, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkStreamErrorStanza__storage_, text), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkStreamErrorStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkStreamErrorStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkClose + +@implementation GtalkClose + + +typedef struct GtalkClose__storage_ { + uint32_t _has_storage_[1]; +} GtalkClose__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkClose class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GtalkClose__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkExtension + +@implementation GtalkExtension + +@dynamic hasId_p, id_p; +@dynamic hasData_p, data_p; + +typedef struct GtalkExtension__storage_ { + uint32_t _has_storage_[1]; + int32_t id_p; + NSString *data_p; +} GtalkExtension__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkExtension_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkExtension__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt32, + }, + { + .name = "data_p", + .dataTypeSpecific.className = NULL, + .number = GtalkExtension_FieldNumber_Data_p, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkExtension__storage_, data_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkExtension class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkExtension__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkMessageStanza + +@implementation GtalkMessageStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasType, type; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasSubject, subject; +@dynamic hasBody, body; +@dynamic hasThread, thread; +@dynamic hasError, error; +@dynamic extensionArray, extensionArray_Count; +@dynamic hasNosave, nosave; +@dynamic hasTimestamp, timestamp; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasRead, read; +@dynamic hasAccountId, accountId; + +typedef struct GtalkMessageStanza__storage_ { + uint32_t _has_storage_[1]; + GtalkMessageStanza_MessageType type; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *from; + NSString *to; + NSString *subject; + NSString *body; + NSString *thread; + GtalkErrorInfo *error; + NSMutableArray *extensionArray; + NSString *persistentId; + int64_t rmqId; + int64_t timestamp; + int64_t accountId; +} GtalkMessageStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, rmqId), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkMessageStanza_MessageType_EnumDescriptor, + .number = GtalkMessageStanza_FieldNumber_Type, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Id_p, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_From, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, from), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_To, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "subject", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Subject, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, subject), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "body", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Body, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, body), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "thread", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Thread, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, thread), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkMessageStanza_FieldNumber_Error, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "extensionArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkMessageStanza_FieldNumber_ExtensionArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, extensionArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "nosave", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Nosave, + .hasIndex = 9, + .offset = 10, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "timestamp", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Timestamp, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, timestamp), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_PersistentId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_StreamId, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "read", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_Read, + .hasIndex = 15, + .offset = 16, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkMessageStanza_FieldNumber_AccountId, + .hasIndex = 17, + .offset = (uint32_t)offsetof(GtalkMessageStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkMessageStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkMessageStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\005\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkMessageStanza_MessageType + +GPBEnumDescriptor *GtalkMessageStanza_MessageType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Normal\000Chat\000Groupchat\000Headline\000Error\000"; + static const int32_t values[] = { + GtalkMessageStanza_MessageType_Normal, + GtalkMessageStanza_MessageType_Chat, + GtalkMessageStanza_MessageType_Groupchat, + GtalkMessageStanza_MessageType_Headline, + GtalkMessageStanza_MessageType_Error, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkMessageStanza_MessageType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkMessageStanza_MessageType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkMessageStanza_MessageType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkMessageStanza_MessageType_Normal: + case GtalkMessageStanza_MessageType_Chat: + case GtalkMessageStanza_MessageType_Groupchat: + case GtalkMessageStanza_MessageType_Headline: + case GtalkMessageStanza_MessageType_Error: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkPresenceStanza + +@implementation GtalkPresenceStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasType, type; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasShow, show; +@dynamic hasStatus, status; +@dynamic hasPriority, priority; +@dynamic hasError, error; +@dynamic extensionArray, extensionArray_Count; +@dynamic hasClient, client; +@dynamic hasAvatarHash, avatarHash; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasCapabilitiesFlags, capabilitiesFlags; +@dynamic hasAccountId, accountId; + +typedef struct GtalkPresenceStanza__storage_ { + uint32_t _has_storage_[1]; + GtalkPresenceStanza_PresenceType type; + GtalkPresenceStanza_ShowType show; + int32_t priority; + GtalkPresenceStanza_ClientType client; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t capabilitiesFlags; + NSString *id_p; + NSString *from; + NSString *to; + NSString *status; + GtalkErrorInfo *error; + NSMutableArray *extensionArray; + NSString *avatarHash; + NSString *persistentId; + int64_t rmqId; + int64_t accountId; +} GtalkPresenceStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, rmqId), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkPresenceStanza_PresenceType_EnumDescriptor, + .number = GtalkPresenceStanza_FieldNumber_Type, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_Id_p, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_From, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, from), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_To, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "show", + .dataTypeSpecific.enumDescFunc = GtalkPresenceStanza_ShowType_EnumDescriptor, + .number = GtalkPresenceStanza_FieldNumber_Show, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, show), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_Status, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "priority", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_Priority, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, priority), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkPresenceStanza_FieldNumber_Error, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "extensionArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkPresenceStanza_FieldNumber_ExtensionArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, extensionArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "client", + .dataTypeSpecific.enumDescFunc = GtalkPresenceStanza_ClientType_EnumDescriptor, + .number = GtalkPresenceStanza_FieldNumber_Client, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, client), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "avatarHash", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_AvatarHash, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, avatarHash), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_PersistentId, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_StreamId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "capabilitiesFlags", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_CapabilitiesFlags, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, capabilitiesFlags), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkPresenceStanza_FieldNumber_AccountId, + .hasIndex = 15, + .offset = (uint32_t)offsetof(GtalkPresenceStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkPresenceStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkPresenceStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\005\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkPresenceStanza_PresenceType + +GPBEnumDescriptor *GtalkPresenceStanza_PresenceType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Unavailable\000Subscribe\000Subscribed\000Unsubsc" + "ribe\000Unsubscribed\000Probe\000Error\000"; + static const int32_t values[] = { + GtalkPresenceStanza_PresenceType_Unavailable, + GtalkPresenceStanza_PresenceType_Subscribe, + GtalkPresenceStanza_PresenceType_Subscribed, + GtalkPresenceStanza_PresenceType_Unsubscribe, + GtalkPresenceStanza_PresenceType_Unsubscribed, + GtalkPresenceStanza_PresenceType_Probe, + GtalkPresenceStanza_PresenceType_Error, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_PresenceType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_PresenceType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_PresenceType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_PresenceType_Unavailable: + case GtalkPresenceStanza_PresenceType_Subscribe: + case GtalkPresenceStanza_PresenceType_Subscribed: + case GtalkPresenceStanza_PresenceType_Unsubscribe: + case GtalkPresenceStanza_PresenceType_Unsubscribed: + case GtalkPresenceStanza_PresenceType_Probe: + case GtalkPresenceStanza_PresenceType_Error: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkPresenceStanza_ShowType + +GPBEnumDescriptor *GtalkPresenceStanza_ShowType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Away\000Chat\000Dnd\000Xa\000"; + static const int32_t values[] = { + GtalkPresenceStanza_ShowType_Away, + GtalkPresenceStanza_ShowType_Chat, + GtalkPresenceStanza_ShowType_Dnd, + GtalkPresenceStanza_ShowType_Xa, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_ShowType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_ShowType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_ShowType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_ShowType_Away: + case GtalkPresenceStanza_ShowType_Chat: + case GtalkPresenceStanza_ShowType_Dnd: + case GtalkPresenceStanza_ShowType_Xa: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkPresenceStanza_ClientType + +GPBEnumDescriptor *GtalkPresenceStanza_ClientType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Mobile\000Android\000"; + static const int32_t values[] = { + GtalkPresenceStanza_ClientType_Mobile, + GtalkPresenceStanza_ClientType_Android, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_ClientType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_ClientType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_ClientType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_ClientType_Mobile: + case GtalkPresenceStanza_ClientType_Android: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkPresenceStanza_CapabilitiesFlags + +GPBEnumDescriptor *GtalkPresenceStanza_CapabilitiesFlags_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "HasVoiceV1\000HasVideoV1\000HasCameraV1\000HasPmu" + "cV1\000"; + static const int32_t values[] = { + GtalkPresenceStanza_CapabilitiesFlags_HasVoiceV1, + GtalkPresenceStanza_CapabilitiesFlags_HasVideoV1, + GtalkPresenceStanza_CapabilitiesFlags_HasCameraV1, + GtalkPresenceStanza_CapabilitiesFlags_HasPmucV1, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPresenceStanza_CapabilitiesFlags) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPresenceStanza_CapabilitiesFlags_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPresenceStanza_CapabilitiesFlags_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPresenceStanza_CapabilitiesFlags_HasVoiceV1: + case GtalkPresenceStanza_CapabilitiesFlags_HasVideoV1: + case GtalkPresenceStanza_CapabilitiesFlags_HasCameraV1: + case GtalkPresenceStanza_CapabilitiesFlags_HasPmucV1: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkBatchPresenceStanza + +@implementation GtalkBatchPresenceStanza + +@dynamic hasId_p, id_p; +@dynamic hasTo, to; +@dynamic presenceArray, presenceArray_Count; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasAccountId, accountId; +@dynamic hasType, type; +@dynamic hasError, error; + +typedef struct GtalkBatchPresenceStanza__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + GtalkBatchPresenceStanza_Type type; + NSString *id_p; + NSString *to; + NSMutableArray *presenceArray; + NSString *persistentId; + GtalkErrorInfo *error; + int64_t accountId; +} GtalkBatchPresenceStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_To, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "presenceArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkPresenceStanza), + .number = GtalkBatchPresenceStanza_FieldNumber_PresenceArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, presenceArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_PersistentId, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_StreamId, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkBatchPresenceStanza_FieldNumber_AccountId, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkBatchPresenceStanza_Type_EnumDescriptor, + .number = GtalkBatchPresenceStanza_FieldNumber_Type, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkBatchPresenceStanza_FieldNumber_Error, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkBatchPresenceStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkBatchPresenceStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkBatchPresenceStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkBatchPresenceStanza_Type + +GPBEnumDescriptor *GtalkBatchPresenceStanza_Type_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Get\000Set\000"; + static const int32_t values[] = { + GtalkBatchPresenceStanza_Type_Get, + GtalkBatchPresenceStanza_Type_Set, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkBatchPresenceStanza_Type) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkBatchPresenceStanza_Type_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkBatchPresenceStanza_Type_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkBatchPresenceStanza_Type_Get: + case GtalkBatchPresenceStanza_Type_Set: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkIqStanza + +@implementation GtalkIqStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasType, type; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasError, error; +@dynamic hasExtension, extension; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasAccountId, accountId; +@dynamic hasStatus, status; + +typedef struct GtalkIqStanza__storage_ { + uint32_t _has_storage_[1]; + GtalkIqStanza_IqType type; + int32_t streamId; + int32_t lastStreamIdReceived; + NSString *id_p; + NSString *from; + NSString *to; + GtalkErrorInfo *error; + GtalkExtension *extension; + NSString *persistentId; + int64_t rmqId; + int64_t accountId; + int64_t status; +} GtalkIqStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, rmqId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkIqStanza_IqType_EnumDescriptor, + .number = GtalkIqStanza_FieldNumber_Type, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldRequired | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_Id_p, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_From, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, from), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_To, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "error", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkErrorInfo), + .number = GtalkIqStanza_FieldNumber_Error, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, error), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "extension", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkExtension), + .number = GtalkIqStanza_FieldNumber_Extension, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, extension), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_PersistentId, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_StreamId, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "accountId", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_AccountId, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, accountId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkIqStanza_FieldNumber_Status, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkIqStanza__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkIqStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkIqStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkIqStanza_IqType + +GPBEnumDescriptor *GtalkIqStanza_IqType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Get\000Set\000Result\000Error\000"; + static const int32_t values[] = { + GtalkIqStanza_IqType_Get, + GtalkIqStanza_IqType_Set, + GtalkIqStanza_IqType_Result, + GtalkIqStanza_IqType_Error, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkIqStanza_IqType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkIqStanza_IqType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkIqStanza_IqType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkIqStanza_IqType_Get: + case GtalkIqStanza_IqType_Set: + case GtalkIqStanza_IqType_Result: + case GtalkIqStanza_IqType_Error: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkAppData + +@implementation GtalkAppData + +@dynamic hasKey, key; +@dynamic hasValue, value; + +typedef struct GtalkAppData__storage_ { + uint32_t _has_storage_[1]; + NSString *key; + NSString *value; +} GtalkAppData__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "key", + .dataTypeSpecific.className = NULL, + .number = GtalkAppData_FieldNumber_Key, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkAppData__storage_, key), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GtalkAppData_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkAppData__storage_, value), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkAppData class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkAppData__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkDataMessageStanza + +@implementation GtalkDataMessageStanza + +@dynamic hasRmqId, rmqId; +@dynamic hasId_p, id_p; +@dynamic hasFrom, from; +@dynamic hasTo, to; +@dynamic hasCategory, category; +@dynamic hasToken, token; +@dynamic appDataArray, appDataArray_Count; +@dynamic hasFromTrustedServer, fromTrustedServer; +@dynamic hasPersistentId, persistentId; +@dynamic hasStreamId, streamId; +@dynamic hasLastStreamIdReceived, lastStreamIdReceived; +@dynamic hasPermission, permission; +@dynamic hasRegId, regId; +@dynamic hasPkgSignature, pkgSignature; +@dynamic hasClientId, clientId; +@dynamic hasDeviceUserId, deviceUserId; +@dynamic hasTtl, ttl; +@dynamic hasSent, sent; +@dynamic hasQueued, queued; +@dynamic hasStatus, status; +@dynamic hasRawData, rawData; +@dynamic hasMaxDelay, maxDelay; +@dynamic hasActualDelay, actualDelay; +@dynamic hasImmediateAck, immediateAck; +@dynamic hasDeliveryReceiptRequested, deliveryReceiptRequested; +@dynamic hasExternalMessageId, externalMessageId; +@dynamic hasFlags, flags; +@dynamic hasCellTower, cellTower; +@dynamic hasPriority, priority; + +typedef struct GtalkDataMessageStanza__storage_ { + uint32_t _has_storage_[1]; + int32_t streamId; + int32_t lastStreamIdReceived; + int32_t ttl; + int32_t queued; + int32_t maxDelay; + int32_t actualDelay; + int32_t priority; + NSString *id_p; + NSString *from; + NSString *to; + NSString *category; + NSString *token; + NSMutableArray *appDataArray; + NSString *persistentId; + NSString *permission; + NSString *regId; + NSString *pkgSignature; + NSString *clientId; + NSData *rawData; + NSString *externalMessageId; + GtalkCellTower *cellTower; + int64_t rmqId; + int64_t deviceUserId; + int64_t sent; + int64_t status; + int64_t flags; +} GtalkDataMessageStanza__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "rmqId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_RmqId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, rmqId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Id_p, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "from", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_From, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, from), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "to", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_To, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, to), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "category", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Category, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, category), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "token", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Token, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, token), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "appDataArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkAppData), + .number = GtalkDataMessageStanza_FieldNumber_AppDataArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, appDataArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "fromTrustedServer", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_FromTrustedServer, + .hasIndex = 6, + .offset = 7, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "persistentId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_PersistentId, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, persistentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "streamId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_StreamId, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, streamId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "lastStreamIdReceived", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_LastStreamIdReceived, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, lastStreamIdReceived), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "permission", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Permission, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, permission), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "regId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_RegId, + .hasIndex = 12, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, regId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "pkgSignature", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_PkgSignature, + .hasIndex = 13, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, pkgSignature), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "clientId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ClientId, + .hasIndex = 14, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, clientId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "deviceUserId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_DeviceUserId, + .hasIndex = 15, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, deviceUserId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "ttl", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Ttl, + .hasIndex = 16, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, ttl), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "sent", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Sent, + .hasIndex = 17, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, sent), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "queued", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Queued, + .hasIndex = 18, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, queued), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Status, + .hasIndex = 19, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "rawData", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_RawData, + .hasIndex = 20, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, rawData), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, + { + .name = "maxDelay", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_MaxDelay, + .hasIndex = 21, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, maxDelay), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "actualDelay", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ActualDelay, + .hasIndex = 22, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, actualDelay), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "immediateAck", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ImmediateAck, + .hasIndex = 23, + .offset = 24, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "deliveryReceiptRequested", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_DeliveryReceiptRequested, + .hasIndex = 25, + .offset = 26, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "externalMessageId", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_ExternalMessageId, + .hasIndex = 27, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, externalMessageId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "flags", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Flags, + .hasIndex = 28, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, flags), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "cellTower", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkCellTower), + .number = GtalkDataMessageStanza_FieldNumber_CellTower, + .hasIndex = 29, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, cellTower), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "priority", + .dataTypeSpecific.className = NULL, + .number = GtalkDataMessageStanza_FieldNumber_Priority, + .hasIndex = 30, + .offset = (uint32_t)offsetof(GtalkDataMessageStanza__storage_, priority), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkDataMessageStanza class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkDataMessageStanza__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkTalkMetadata + +@implementation GtalkTalkMetadata + +@dynamic hasForeground, foreground; + +typedef struct GtalkTalkMetadata__storage_ { + uint32_t _has_storage_[1]; +} GtalkTalkMetadata__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "foreground", + .dataTypeSpecific.className = NULL, + .number = GtalkTalkMetadata_FieldNumber_Foreground, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkTalkMetadata class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkTalkMetadata__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkCellTower + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" + +@implementation GtalkCellTower + +@dynamic hasId_p, id_p; +@dynamic hasKnownCongestionStatus, knownCongestionStatus; + +typedef struct GtalkCellTower__storage_ { + uint32_t _has_storage_[1]; + int32_t knownCongestionStatus; + NSString *id_p; +} GtalkCellTower__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkCellTower_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkCellTower__storage_, id_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "knownCongestionStatus", + .dataTypeSpecific.className = NULL, + .number = GtalkCellTower_FieldNumber_KnownCongestionStatus, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkCellTower__storage_, knownCongestionStatus), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkCellTower class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkCellTower__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma clang diagnostic pop + +#pragma mark - GtalkClientEvent + +@implementation GtalkClientEvent + +@dynamic hasType, type; +@dynamic hasNumberDiscardedEvents, numberDiscardedEvents; +@dynamic hasNetworkType, networkType; +@dynamic hasNetworkPort, networkPort; +@dynamic hasTimeConnectionStartedMs, timeConnectionStartedMs; +@dynamic hasTimeConnectionEndedMs, timeConnectionEndedMs; +@dynamic hasErrorCode, errorCode; +@dynamic hasTimeConnectionEstablishedMs, timeConnectionEstablishedMs; +@dynamic hasMcsReconnectAction, mcsReconnectAction; + +typedef struct GtalkClientEvent__storage_ { + uint32_t _has_storage_[1]; + GtalkClientEvent_Type type; + uint32_t numberDiscardedEvents; + int32_t networkType; + int32_t networkPort; + int32_t errorCode; + GtalkClientEvent_McsReconnectAction mcsReconnectAction; + uint64_t timeConnectionStartedMs; + uint64_t timeConnectionEndedMs; + uint64_t timeConnectionEstablishedMs; +} GtalkClientEvent__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "type", + .dataTypeSpecific.enumDescFunc = GtalkClientEvent_Type_EnumDescriptor, + .number = GtalkClientEvent_FieldNumber_Type, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, type), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "numberDiscardedEvents", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_NumberDiscardedEvents, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, numberDiscardedEvents), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt32, + }, + { + .name = "networkType", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_NetworkType, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, networkType), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "networkPort", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_NetworkPort, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, networkPort), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "timeConnectionStartedMs", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_TimeConnectionStartedMs, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, timeConnectionStartedMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "timeConnectionEndedMs", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_TimeConnectionEndedMs, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, timeConnectionEndedMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "errorCode", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_ErrorCode, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, errorCode), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "timeConnectionEstablishedMs", + .dataTypeSpecific.className = NULL, + .number = GtalkClientEvent_FieldNumber_TimeConnectionEstablishedMs, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, timeConnectionEstablishedMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "mcsReconnectAction", + .dataTypeSpecific.enumDescFunc = GtalkClientEvent_McsReconnectAction_EnumDescriptor, + .number = GtalkClientEvent_FieldNumber_McsReconnectAction, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkClientEvent__storage_, mcsReconnectAction), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkClientEvent class] + rootClass:[GtalkGtalkCoreRoot class] + file:GtalkGtalkCoreRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkClientEvent__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkClientEvent_Type + +GPBEnumDescriptor *GtalkClientEvent_Type_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Unknown\000DiscardedEvents\000FailedConnection" + "\000SuccessfulConnection\000McsReconnectReques" + "t\000FailedSocketCreationMcsReconnect\000McsRe" + "connectLimited\000"; + static const int32_t values[] = { + GtalkClientEvent_Type_Unknown, + GtalkClientEvent_Type_DiscardedEvents, + GtalkClientEvent_Type_FailedConnection, + GtalkClientEvent_Type_SuccessfulConnection, + GtalkClientEvent_Type_McsReconnectRequest, + GtalkClientEvent_Type_FailedSocketCreationMcsReconnect, + GtalkClientEvent_Type_McsReconnectLimited, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkClientEvent_Type) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkClientEvent_Type_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkClientEvent_Type_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkClientEvent_Type_Unknown: + case GtalkClientEvent_Type_DiscardedEvents: + case GtalkClientEvent_Type_FailedConnection: + case GtalkClientEvent_Type_SuccessfulConnection: + case GtalkClientEvent_Type_McsReconnectRequest: + case GtalkClientEvent_Type_FailedSocketCreationMcsReconnect: + case GtalkClientEvent_Type_McsReconnectLimited: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkClientEvent_McsReconnectAction + +GPBEnumDescriptor *GtalkClientEvent_McsReconnectAction_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "None\000NotConnected\000TooSoon\000"; + static const int32_t values[] = { + GtalkClientEvent_McsReconnectAction_None, + GtalkClientEvent_McsReconnectAction_NotConnected, + GtalkClientEvent_McsReconnectAction_TooSoon, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkClientEvent_McsReconnectAction) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkClientEvent_McsReconnectAction_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkClientEvent_McsReconnectAction_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkClientEvent_McsReconnectAction_None: + case GtalkClientEvent_McsReconnectAction_NotConnected: + case GtalkClientEvent_McsReconnectAction_TooSoon: + return YES; + default: + return NO; + } +} + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h new file mode 100644 index 0000000..f461884 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h @@ -0,0 +1,617 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_extensions.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GtalkOtrItem; +@class GtalkPhoto; +@class GtalkRosterItem; +@class GtalkSharedStatus_StatusList; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GtalkRosterItem_SubscriptionType + +typedef GPB_ENUM(GtalkRosterItem_SubscriptionType) { + GtalkRosterItem_SubscriptionType_None = 0, + GtalkRosterItem_SubscriptionType_To = 1, + GtalkRosterItem_SubscriptionType_From = 2, + GtalkRosterItem_SubscriptionType_Both = 3, + GtalkRosterItem_SubscriptionType_Remove = 4, +}; + +GPBEnumDescriptor *GtalkRosterItem_SubscriptionType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkRosterItem_SubscriptionType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkRosterItem_AskType + +typedef GPB_ENUM(GtalkRosterItem_AskType) { + GtalkRosterItem_AskType_Subscribe = 0, +}; + +GPBEnumDescriptor *GtalkRosterItem_AskType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkRosterItem_AskType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkRosterItem_DisplayType + +typedef GPB_ENUM(GtalkRosterItem_DisplayType) { + GtalkRosterItem_DisplayType_Blocked = 0, + GtalkRosterItem_DisplayType_Hidden = 1, + GtalkRosterItem_DisplayType_Pinned = 2, +}; + +GPBEnumDescriptor *GtalkRosterItem_DisplayType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkRosterItem_DisplayType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkSharedStatus_ShowType + +typedef GPB_ENUM(GtalkSharedStatus_ShowType) { + GtalkSharedStatus_ShowType_Default = 0, + GtalkSharedStatus_ShowType_Dnd = 1, +}; + +GPBEnumDescriptor *GtalkSharedStatus_ShowType_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkSharedStatus_ShowType_IsValidValue(int32_t value); + +#pragma mark - Enum GtalkPostAuthBatchQuery_CapabilitiesExtFlags + +typedef GPB_ENUM(GtalkPostAuthBatchQuery_CapabilitiesExtFlags) { + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVoiceV1 = 1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVideoV1 = 2, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasCameraV1 = 4, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasPmucV1 = 8, +}; + +GPBEnumDescriptor *GtalkPostAuthBatchQuery_CapabilitiesExtFlags_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GtalkPostAuthBatchQuery_CapabilitiesExtFlags_IsValidValue(int32_t value); + +#pragma mark - GtalkGtalkExtensionsRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GtalkGtalkExtensionsRoot : GPBRootObject +@end + +#pragma mark - GtalkRosterQuery + +typedef GPB_ENUM(GtalkRosterQuery_FieldNumber) { + GtalkRosterQuery_FieldNumber_Etag = 1, + GtalkRosterQuery_FieldNumber_NotModified = 2, + GtalkRosterQuery_FieldNumber_ItemArray = 3, + GtalkRosterQuery_FieldNumber_AvatarWidth = 4, + GtalkRosterQuery_FieldNumber_AvatarHeight = 5, +}; + +@interface GtalkRosterQuery : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *etag; +/** Test to see if @c etag has been set. */ +@property(nonatomic, readwrite) BOOL hasEtag; + + +@property(nonatomic, readwrite) BOOL notModified; + +@property(nonatomic, readwrite) BOOL hasNotModified; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *itemArray; +/** The number of items in @c itemArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger itemArray_Count; + + +@property(nonatomic, readwrite) int32_t avatarWidth; + +@property(nonatomic, readwrite) BOOL hasAvatarWidth; + +@property(nonatomic, readwrite) int32_t avatarHeight; + +@property(nonatomic, readwrite) BOOL hasAvatarHeight; +@end + +#pragma mark - GtalkRosterItem + +typedef GPB_ENUM(GtalkRosterItem_FieldNumber) { + GtalkRosterItem_FieldNumber_Jid = 1, + GtalkRosterItem_FieldNumber_Name = 2, + GtalkRosterItem_FieldNumber_Subscription = 3, + GtalkRosterItem_FieldNumber_Ask = 4, + GtalkRosterItem_FieldNumber_GroupArray = 5, + GtalkRosterItem_FieldNumber_QuickContact = 6, + GtalkRosterItem_FieldNumber_Display = 7, + GtalkRosterItem_FieldNumber_Rejected = 8, +}; + +@interface GtalkRosterItem : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; +/** Test to see if @c name has been set. */ +@property(nonatomic, readwrite) BOOL hasName; + + +@property(nonatomic, readwrite) GtalkRosterItem_SubscriptionType subscription; + +@property(nonatomic, readwrite) BOOL hasSubscription; + +@property(nonatomic, readwrite) GtalkRosterItem_AskType ask; + +@property(nonatomic, readwrite) BOOL hasAsk; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *groupArray; +/** The number of items in @c groupArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger groupArray_Count; + + +@property(nonatomic, readwrite) BOOL quickContact; + +@property(nonatomic, readwrite) BOOL hasQuickContact; + +@property(nonatomic, readwrite) GtalkRosterItem_DisplayType display; + +@property(nonatomic, readwrite) BOOL hasDisplay; + +@property(nonatomic, readwrite) BOOL rejected; + +@property(nonatomic, readwrite) BOOL hasRejected; +@end + +#pragma mark - GtalkRmqLastId + +typedef GPB_ENUM(GtalkRmqLastId_FieldNumber) { + GtalkRmqLastId_FieldNumber_Id_p = 1, +}; + +@interface GtalkRmqLastId : GPBMessage + + +@property(nonatomic, readwrite) int64_t id_p; + +@property(nonatomic, readwrite) BOOL hasId_p; +@end + +#pragma mark - GtalkRmqAck + +typedef GPB_ENUM(GtalkRmqAck_FieldNumber) { + GtalkRmqAck_FieldNumber_Id_p = 1, +}; + +@interface GtalkRmqAck : GPBMessage + + +@property(nonatomic, readwrite) int64_t id_p; + +@property(nonatomic, readwrite) BOOL hasId_p; +@end + +#pragma mark - GtalkVCard + +typedef GPB_ENUM(GtalkVCard_FieldNumber) { + GtalkVCard_FieldNumber_Version = 1, + GtalkVCard_FieldNumber_FullName = 2, + GtalkVCard_FieldNumber_Photo = 3, + GtalkVCard_FieldNumber_AvatarHash = 4, + GtalkVCard_FieldNumber_Modified = 5, +}; + +@interface GtalkVCard : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *version; +/** Test to see if @c version has been set. */ +@property(nonatomic, readwrite) BOOL hasVersion; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *fullName; +/** Test to see if @c fullName has been set. */ +@property(nonatomic, readwrite) BOOL hasFullName; + + +@property(nonatomic, readwrite, strong, null_resettable) GtalkPhoto *photo; +/** Test to see if @c photo has been set. */ +@property(nonatomic, readwrite) BOOL hasPhoto; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *avatarHash; +/** Test to see if @c avatarHash has been set. */ +@property(nonatomic, readwrite) BOOL hasAvatarHash; + + +@property(nonatomic, readwrite) BOOL modified; + +@property(nonatomic, readwrite) BOOL hasModified; +@end + +#pragma mark - GtalkPhoto + +typedef GPB_ENUM(GtalkPhoto_FieldNumber) { + GtalkPhoto_FieldNumber_Type = 1, + GtalkPhoto_FieldNumber_Data_p = 2, +}; + +@interface GtalkPhoto : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *type; +/** Test to see if @c type has been set. */ +@property(nonatomic, readwrite) BOOL hasType; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *data_p; +/** Test to see if @c data_p has been set. */ +@property(nonatomic, readwrite) BOOL hasData_p; + +@end + +#pragma mark - GtalkChatRead + +typedef GPB_ENUM(GtalkChatRead_FieldNumber) { + GtalkChatRead_FieldNumber_User = 1, +}; + +@interface GtalkChatRead : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + +@end + +#pragma mark - GtalkChatClosed + +typedef GPB_ENUM(GtalkChatClosed_FieldNumber) { + GtalkChatClosed_FieldNumber_User = 1, +}; + +@interface GtalkChatClosed : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *user; +/** Test to see if @c user has been set. */ +@property(nonatomic, readwrite) BOOL hasUser; + +@end + +#pragma mark - GtalkCapabilities + +typedef GPB_ENUM(GtalkCapabilities_FieldNumber) { + GtalkCapabilities_FieldNumber_Node = 1, + GtalkCapabilities_FieldNumber_Ver = 2, + GtalkCapabilities_FieldNumber_Ext = 3, + GtalkCapabilities_FieldNumber_Hash_p = 4, +}; + +@interface GtalkCapabilities : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *node; +/** Test to see if @c node has been set. */ +@property(nonatomic, readwrite) BOOL hasNode; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ver; +/** Test to see if @c ver has been set. */ +@property(nonatomic, readwrite) BOOL hasVer; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *ext; +/** Test to see if @c ext has been set. */ +@property(nonatomic, readwrite) BOOL hasExt; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *hash_p; +/** Test to see if @c hash_p has been set. */ +@property(nonatomic, readwrite) BOOL hasHash_p; + +@end + +#pragma mark - GtalkSharedStatus + +typedef GPB_ENUM(GtalkSharedStatus_FieldNumber) { + GtalkSharedStatus_FieldNumber_StatusMax = 1, + GtalkSharedStatus_FieldNumber_StatusListMax = 2, + GtalkSharedStatus_FieldNumber_StatusListContentsMax = 3, + GtalkSharedStatus_FieldNumber_Status = 4, + GtalkSharedStatus_FieldNumber_Show = 5, + GtalkSharedStatus_FieldNumber_StatusListArray = 6, + GtalkSharedStatus_FieldNumber_Invisible = 9, + GtalkSharedStatus_FieldNumber_StatusMinVersion = 10, +}; + +@interface GtalkSharedStatus : GPBMessage + + +@property(nonatomic, readwrite) int32_t statusMax; + +@property(nonatomic, readwrite) BOOL hasStatusMax; + +@property(nonatomic, readwrite) int32_t statusListMax; + +@property(nonatomic, readwrite) BOOL hasStatusListMax; + +@property(nonatomic, readwrite) int32_t statusListContentsMax; + +@property(nonatomic, readwrite) BOOL hasStatusListContentsMax; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *status; +/** Test to see if @c status has been set. */ +@property(nonatomic, readwrite) BOOL hasStatus; + + +@property(nonatomic, readwrite) GtalkSharedStatus_ShowType show; + +@property(nonatomic, readwrite) BOOL hasShow; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *statusListArray; +/** The number of items in @c statusListArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger statusListArray_Count; + + +@property(nonatomic, readwrite) BOOL invisible; + +@property(nonatomic, readwrite) BOOL hasInvisible; + +@property(nonatomic, readwrite) int32_t statusMinVersion; + +@property(nonatomic, readwrite) BOOL hasStatusMinVersion; +@end + +#pragma mark - GtalkSharedStatus_StatusList + +typedef GPB_ENUM(GtalkSharedStatus_StatusList_FieldNumber) { + GtalkSharedStatus_StatusList_FieldNumber_Show = 7, + GtalkSharedStatus_StatusList_FieldNumber_StatusArray = 8, +}; + +@interface GtalkSharedStatus_StatusList : GPBMessage + + +@property(nonatomic, readwrite) GtalkSharedStatus_ShowType show; + +@property(nonatomic, readwrite) BOOL hasShow; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *statusArray; +/** The number of items in @c statusArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger statusArray_Count; + +@end + +#pragma mark - GtalkOtrQuery + +typedef GPB_ENUM(GtalkOtrQuery_FieldNumber) { + GtalkOtrQuery_FieldNumber_NosaveDefault = 1, + GtalkOtrQuery_FieldNumber_ItemArray = 2, + GtalkOtrQuery_FieldNumber_Etag = 3, + GtalkOtrQuery_FieldNumber_NotModified = 4, +}; + +@interface GtalkOtrQuery : GPBMessage + + +@property(nonatomic, readwrite) BOOL nosaveDefault; + +@property(nonatomic, readwrite) BOOL hasNosaveDefault; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *itemArray; +/** The number of items in @c itemArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger itemArray_Count; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *etag; +/** Test to see if @c etag has been set. */ +@property(nonatomic, readwrite) BOOL hasEtag; + + +@property(nonatomic, readwrite) BOOL notModified; + +@property(nonatomic, readwrite) BOOL hasNotModified; +@end + +#pragma mark - GtalkOtrItem + +typedef GPB_ENUM(GtalkOtrItem_FieldNumber) { + GtalkOtrItem_FieldNumber_Jid = 1, + GtalkOtrItem_FieldNumber_Nosave = 2, + GtalkOtrItem_FieldNumber_ChangedByBuddy = 3, +}; + +@interface GtalkOtrItem : GPBMessage + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *jid; +/** Test to see if @c jid has been set. */ +@property(nonatomic, readwrite) BOOL hasJid; + + +@property(nonatomic, readwrite) BOOL nosave; + +@property(nonatomic, readwrite) BOOL hasNosave; + +@property(nonatomic, readwrite) BOOL changedByBuddy; + +@property(nonatomic, readwrite) BOOL hasChangedByBuddy; +@end + +#pragma mark - GtalkIdle + +typedef GPB_ENUM(GtalkIdle_FieldNumber) { + GtalkIdle_FieldNumber_Idle = 1, + GtalkIdle_FieldNumber_Away = 2, +}; + +@interface GtalkIdle : GPBMessage + + +@property(nonatomic, readwrite) BOOL idle; + +@property(nonatomic, readwrite) BOOL hasIdle; + +@property(nonatomic, readwrite) BOOL away; + +@property(nonatomic, readwrite) BOOL hasAway; +@end + +#pragma mark - GtalkPostAuthBatchQuery + +typedef GPB_ENUM(GtalkPostAuthBatchQuery_FieldNumber) { + GtalkPostAuthBatchQuery_FieldNumber_Available = 1, + GtalkPostAuthBatchQuery_FieldNumber_DeviceIdle = 2, + GtalkPostAuthBatchQuery_FieldNumber_MobileIndicator = 3, + GtalkPostAuthBatchQuery_FieldNumber_SharedStatusVersion = 4, + GtalkPostAuthBatchQuery_FieldNumber_RosterEtag = 5, + GtalkPostAuthBatchQuery_FieldNumber_OtrEtag = 6, + GtalkPostAuthBatchQuery_FieldNumber_AvatarHash = 7, + GtalkPostAuthBatchQuery_FieldNumber_VcardQueryStanzaId = 8, + GtalkPostAuthBatchQuery_FieldNumber_CapabilitiesExtFlags = 9, +}; + +@interface GtalkPostAuthBatchQuery : GPBMessage + + +@property(nonatomic, readwrite) BOOL available; + +@property(nonatomic, readwrite) BOOL hasAvailable; + +@property(nonatomic, readwrite) BOOL deviceIdle; + +@property(nonatomic, readwrite) BOOL hasDeviceIdle; + +@property(nonatomic, readwrite) BOOL mobileIndicator; + +@property(nonatomic, readwrite) BOOL hasMobileIndicator; + +@property(nonatomic, readwrite) int32_t sharedStatusVersion; + +@property(nonatomic, readwrite) BOOL hasSharedStatusVersion; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *rosterEtag; +/** Test to see if @c rosterEtag has been set. */ +@property(nonatomic, readwrite) BOOL hasRosterEtag; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *otrEtag; +/** Test to see if @c otrEtag has been set. */ +@property(nonatomic, readwrite) BOOL hasOtrEtag; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *avatarHash; +/** Test to see if @c avatarHash has been set. */ +@property(nonatomic, readwrite) BOOL hasAvatarHash; + + +@property(nonatomic, readwrite, copy, null_resettable) NSString *vcardQueryStanzaId; +/** Test to see if @c vcardQueryStanzaId has been set. */ +@property(nonatomic, readwrite) BOOL hasVcardQueryStanzaId; + + +@property(nonatomic, readwrite) int32_t capabilitiesExtFlags; + +@property(nonatomic, readwrite) BOOL hasCapabilitiesExtFlags; +@end + +#pragma mark - GtalkStreamAck + +@interface GtalkStreamAck : GPBMessage + +@end + +#pragma mark - GtalkSelectiveAck + +typedef GPB_ENUM(GtalkSelectiveAck_FieldNumber) { + GtalkSelectiveAck_FieldNumber_IdArray = 1, +}; + +@interface GtalkSelectiveAck : GPBMessage + + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *idArray; +/** The number of items in @c idArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger idArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m new file mode 100644 index 0000000..e41d416 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m @@ -0,0 +1,1407 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: buzz/mobile/proto/gtalk_extensions.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + + #import "GtalkExtensions.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GtalkGtalkExtensionsRoot + +@implementation GtalkGtalkExtensionsRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GtalkGtalkExtensionsRoot_FileDescriptor + +static GPBFileDescriptor *GtalkGtalkExtensionsRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"mobilegtalk" + objcPrefix:@"Gtalk" + syntax:GPBFileSyntaxProto2]; + } + return descriptor; +} + +#pragma mark - GtalkRosterQuery + +@implementation GtalkRosterQuery + +@dynamic hasEtag, etag; +@dynamic hasNotModified, notModified; +@dynamic itemArray, itemArray_Count; +@dynamic hasAvatarWidth, avatarWidth; +@dynamic hasAvatarHeight, avatarHeight; + +typedef struct GtalkRosterQuery__storage_ { + uint32_t _has_storage_[1]; + int32_t avatarWidth; + int32_t avatarHeight; + NSString *etag; + NSMutableArray *itemArray; +} GtalkRosterQuery__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "etag", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_Etag, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, etag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "notModified", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_NotModified, + .hasIndex = 1, + .offset = 2, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "itemArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkRosterItem), + .number = GtalkRosterQuery_FieldNumber_ItemArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, itemArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "avatarWidth", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_AvatarWidth, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, avatarWidth), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt32, + }, + { + .name = "avatarHeight", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterQuery_FieldNumber_AvatarHeight, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkRosterQuery__storage_, avatarHeight), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRosterQuery class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRosterQuery__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\002\004\013\000\005\014\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkRosterItem + +@implementation GtalkRosterItem + +@dynamic hasJid, jid; +@dynamic hasName, name; +@dynamic hasSubscription, subscription; +@dynamic hasAsk, ask; +@dynamic groupArray, groupArray_Count; +@dynamic hasQuickContact, quickContact; +@dynamic hasDisplay, display; +@dynamic hasRejected, rejected; + +typedef struct GtalkRosterItem__storage_ { + uint32_t _has_storage_[1]; + GtalkRosterItem_SubscriptionType subscription; + GtalkRosterItem_AskType ask; + GtalkRosterItem_DisplayType display; + NSString *jid; + NSString *name; + NSMutableArray *groupArray; +} GtalkRosterItem__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_Jid, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, jid), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_Name, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "subscription", + .dataTypeSpecific.enumDescFunc = GtalkRosterItem_SubscriptionType_EnumDescriptor, + .number = GtalkRosterItem_FieldNumber_Subscription, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, subscription), + .flags = (GPBFieldFlags)(GPBFieldRequired | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "ask", + .dataTypeSpecific.enumDescFunc = GtalkRosterItem_AskType_EnumDescriptor, + .number = GtalkRosterItem_FieldNumber_Ask, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, ask), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "groupArray", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_GroupArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, groupArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "quickContact", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_QuickContact, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "display", + .dataTypeSpecific.enumDescFunc = GtalkRosterItem_DisplayType_EnumDescriptor, + .number = GtalkRosterItem_FieldNumber_Display, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkRosterItem__storage_, display), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "rejected", + .dataTypeSpecific.className = NULL, + .number = GtalkRosterItem_FieldNumber_Rejected, + .hasIndex = 7, + .offset = 8, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRosterItem class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRosterItem__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkRosterItem_SubscriptionType + +GPBEnumDescriptor *GtalkRosterItem_SubscriptionType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "None\000To\000From\000Both\000Remove\000"; + static const int32_t values[] = { + GtalkRosterItem_SubscriptionType_None, + GtalkRosterItem_SubscriptionType_To, + GtalkRosterItem_SubscriptionType_From, + GtalkRosterItem_SubscriptionType_Both, + GtalkRosterItem_SubscriptionType_Remove, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkRosterItem_SubscriptionType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkRosterItem_SubscriptionType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkRosterItem_SubscriptionType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkRosterItem_SubscriptionType_None: + case GtalkRosterItem_SubscriptionType_To: + case GtalkRosterItem_SubscriptionType_From: + case GtalkRosterItem_SubscriptionType_Both: + case GtalkRosterItem_SubscriptionType_Remove: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkRosterItem_AskType + +GPBEnumDescriptor *GtalkRosterItem_AskType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Subscribe\000"; + static const int32_t values[] = { + GtalkRosterItem_AskType_Subscribe, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkRosterItem_AskType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkRosterItem_AskType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkRosterItem_AskType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkRosterItem_AskType_Subscribe: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GtalkRosterItem_DisplayType + +GPBEnumDescriptor *GtalkRosterItem_DisplayType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Blocked\000Hidden\000Pinned\000"; + static const int32_t values[] = { + GtalkRosterItem_DisplayType_Blocked, + GtalkRosterItem_DisplayType_Hidden, + GtalkRosterItem_DisplayType_Pinned, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkRosterItem_DisplayType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkRosterItem_DisplayType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkRosterItem_DisplayType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkRosterItem_DisplayType_Blocked: + case GtalkRosterItem_DisplayType_Hidden: + case GtalkRosterItem_DisplayType_Pinned: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkRmqLastId + +@implementation GtalkRmqLastId + +@dynamic hasId_p, id_p; + +typedef struct GtalkRmqLastId__storage_ { + uint32_t _has_storage_[1]; + int64_t id_p; +} GtalkRmqLastId__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkRmqLastId_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRmqLastId__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRmqLastId class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRmqLastId__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkRmqAck + +@implementation GtalkRmqAck + +@dynamic hasId_p, id_p; + +typedef struct GtalkRmqAck__storage_ { + uint32_t _has_storage_[1]; + int64_t id_p; +} GtalkRmqAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "id_p", + .dataTypeSpecific.className = NULL, + .number = GtalkRmqAck_FieldNumber_Id_p, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkRmqAck__storage_, id_p), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkRmqAck class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkRmqAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkVCard + +@implementation GtalkVCard + +@dynamic hasVersion, version; +@dynamic hasFullName, fullName; +@dynamic hasPhoto, photo; +@dynamic hasAvatarHash, avatarHash; +@dynamic hasModified, modified; + +typedef struct GtalkVCard__storage_ { + uint32_t _has_storage_[1]; + NSString *version; + NSString *fullName; + GtalkPhoto *photo; + NSString *avatarHash; +} GtalkVCard__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "version", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_Version, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, version), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "fullName", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_FullName, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, fullName), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "photo", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkPhoto), + .number = GtalkVCard_FieldNumber_Photo, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, photo), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "avatarHash", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_AvatarHash, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkVCard__storage_, avatarHash), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "modified", + .dataTypeSpecific.className = NULL, + .number = GtalkVCard_FieldNumber_Modified, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkVCard class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkVCard__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkPhoto + +@implementation GtalkPhoto + +@dynamic hasType, type; +@dynamic hasData_p, data_p; + +typedef struct GtalkPhoto__storage_ { + uint32_t _has_storage_[1]; + NSString *type; + NSString *data_p; +} GtalkPhoto__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "type", + .dataTypeSpecific.className = NULL, + .number = GtalkPhoto_FieldNumber_Type, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkPhoto__storage_, type), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "data_p", + .dataTypeSpecific.className = NULL, + .number = GtalkPhoto_FieldNumber_Data_p, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkPhoto__storage_, data_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkPhoto class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkPhoto__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkChatRead + +@implementation GtalkChatRead + +@dynamic hasUser, user; + +typedef struct GtalkChatRead__storage_ { + uint32_t _has_storage_[1]; + NSString *user; +} GtalkChatRead__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkChatRead_FieldNumber_User, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkChatRead__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkChatRead class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkChatRead__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkChatClosed + +@implementation GtalkChatClosed + +@dynamic hasUser, user; + +typedef struct GtalkChatClosed__storage_ { + uint32_t _has_storage_[1]; + NSString *user; +} GtalkChatClosed__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "user", + .dataTypeSpecific.className = NULL, + .number = GtalkChatClosed_FieldNumber_User, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkChatClosed__storage_, user), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkChatClosed class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkChatClosed__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkCapabilities + +@implementation GtalkCapabilities + +@dynamic hasNode, node; +@dynamic hasVer, ver; +@dynamic hasExt, ext; +@dynamic hasHash_p, hash_p; + +typedef struct GtalkCapabilities__storage_ { + uint32_t _has_storage_[1]; + NSString *node; + NSString *ver; + NSString *ext; + NSString *hash_p; +} GtalkCapabilities__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "node", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Node, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, node), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "ver", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Ver, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, ver), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "ext", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Ext, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, ext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "hash_p", + .dataTypeSpecific.className = NULL, + .number = GtalkCapabilities_FieldNumber_Hash_p, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkCapabilities__storage_, hash_p), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkCapabilities class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkCapabilities__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkSharedStatus + +@implementation GtalkSharedStatus + +@dynamic hasStatusMax, statusMax; +@dynamic hasStatusListMax, statusListMax; +@dynamic hasStatusListContentsMax, statusListContentsMax; +@dynamic hasStatus, status; +@dynamic hasShow, show; +@dynamic statusListArray, statusListArray_Count; +@dynamic hasInvisible, invisible; +@dynamic hasStatusMinVersion, statusMinVersion; + +typedef struct GtalkSharedStatus__storage_ { + uint32_t _has_storage_[1]; + int32_t statusMax; + int32_t statusListMax; + int32_t statusListContentsMax; + GtalkSharedStatus_ShowType show; + int32_t statusMinVersion; + NSString *status; + NSMutableArray *statusListArray; +} GtalkSharedStatus__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "statusMax", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusMax, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusMax), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "statusListMax", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusListMax, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusListMax), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "statusListContentsMax", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusListContentsMax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusListContentsMax), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "status", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_Status, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, status), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "show", + .dataTypeSpecific.enumDescFunc = GtalkSharedStatus_ShowType_EnumDescriptor, + .number = GtalkSharedStatus_FieldNumber_Show, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, show), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "statusListArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkSharedStatus_StatusList), + .number = GtalkSharedStatus_FieldNumber_StatusListArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusListArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeGroup, + }, + { + .name = "invisible", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_Invisible, + .hasIndex = 5, + .offset = 6, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "statusMinVersion", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_FieldNumber_StatusMinVersion, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkSharedStatus__storage_, statusMinVersion), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSharedStatus class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSharedStatus__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkSharedStatus_ShowType + +GPBEnumDescriptor *GtalkSharedStatus_ShowType_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "Default\000Dnd\000"; + static const int32_t values[] = { + GtalkSharedStatus_ShowType_Default, + GtalkSharedStatus_ShowType_Dnd, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkSharedStatus_ShowType) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkSharedStatus_ShowType_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkSharedStatus_ShowType_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkSharedStatus_ShowType_Default: + case GtalkSharedStatus_ShowType_Dnd: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkSharedStatus_StatusList + +@implementation GtalkSharedStatus_StatusList + +@dynamic hasShow, show; +@dynamic statusArray, statusArray_Count; + +typedef struct GtalkSharedStatus_StatusList__storage_ { + uint32_t _has_storage_[1]; + GtalkSharedStatus_ShowType show; + NSMutableArray *statusArray; +} GtalkSharedStatus_StatusList__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "show", + .dataTypeSpecific.enumDescFunc = GtalkSharedStatus_ShowType_EnumDescriptor, + .number = GtalkSharedStatus_StatusList_FieldNumber_Show, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkSharedStatus_StatusList__storage_, show), + .flags = (GPBFieldFlags)(GPBFieldRequired | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "statusArray", + .dataTypeSpecific.className = NULL, + .number = GtalkSharedStatus_StatusList_FieldNumber_StatusArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkSharedStatus_StatusList__storage_, statusArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSharedStatus_StatusList class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSharedStatus_StatusList__storage_) + flags:GPBDescriptorInitializationFlag_None]; + [localDescriptor setupContainingMessageClassName:GPBStringifySymbol(GtalkSharedStatus)]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkOtrQuery + +@implementation GtalkOtrQuery + +@dynamic hasNosaveDefault, nosaveDefault; +@dynamic itemArray, itemArray_Count; +@dynamic hasEtag, etag; +@dynamic hasNotModified, notModified; + +typedef struct GtalkOtrQuery__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *itemArray; + NSString *etag; +} GtalkOtrQuery__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "nosaveDefault", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrQuery_FieldNumber_NosaveDefault, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "itemArray", + .dataTypeSpecific.className = GPBStringifySymbol(GtalkOtrItem), + .number = GtalkOtrQuery_FieldNumber_ItemArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkOtrQuery__storage_, itemArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "etag", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrQuery_FieldNumber_Etag, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GtalkOtrQuery__storage_, etag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "notModified", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrQuery_FieldNumber_NotModified, + .hasIndex = 3, + .offset = 4, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkOtrQuery class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkOtrQuery__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkOtrItem + +@implementation GtalkOtrItem + +@dynamic hasJid, jid; +@dynamic hasNosave, nosave; +@dynamic hasChangedByBuddy, changedByBuddy; + +typedef struct GtalkOtrItem__storage_ { + uint32_t _has_storage_[1]; + NSString *jid; +} GtalkOtrItem__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "jid", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrItem_FieldNumber_Jid, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GtalkOtrItem__storage_, jid), + .flags = GPBFieldRequired, + .dataType = GPBDataTypeString, + }, + { + .name = "nosave", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrItem_FieldNumber_Nosave, + .hasIndex = 1, + .offset = 2, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "changedByBuddy", + .dataTypeSpecific.className = NULL, + .number = GtalkOtrItem_FieldNumber_ChangedByBuddy, + .hasIndex = 3, + .offset = 4, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkOtrItem class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkOtrItem__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkIdle + +@implementation GtalkIdle + +@dynamic hasIdle, idle; +@dynamic hasAway, away; + +typedef struct GtalkIdle__storage_ { + uint32_t _has_storage_[1]; +} GtalkIdle__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "idle", + .dataTypeSpecific.className = NULL, + .number = GtalkIdle_FieldNumber_Idle, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "away", + .dataTypeSpecific.className = NULL, + .number = GtalkIdle_FieldNumber_Away, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkIdle class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkIdle__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkPostAuthBatchQuery + +@implementation GtalkPostAuthBatchQuery + +@dynamic hasAvailable, available; +@dynamic hasDeviceIdle, deviceIdle; +@dynamic hasMobileIndicator, mobileIndicator; +@dynamic hasSharedStatusVersion, sharedStatusVersion; +@dynamic hasRosterEtag, rosterEtag; +@dynamic hasOtrEtag, otrEtag; +@dynamic hasAvatarHash, avatarHash; +@dynamic hasVcardQueryStanzaId, vcardQueryStanzaId; +@dynamic hasCapabilitiesExtFlags, capabilitiesExtFlags; + +typedef struct GtalkPostAuthBatchQuery__storage_ { + uint32_t _has_storage_[1]; + int32_t sharedStatusVersion; + int32_t capabilitiesExtFlags; + NSString *rosterEtag; + NSString *otrEtag; + NSString *avatarHash; + NSString *vcardQueryStanzaId; +} GtalkPostAuthBatchQuery__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "available", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_Available, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldRequired, + .dataType = GPBDataTypeBool, + }, + { + .name = "deviceIdle", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_DeviceIdle, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "mobileIndicator", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_MobileIndicator, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "sharedStatusVersion", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_SharedStatusVersion, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, sharedStatusVersion), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "rosterEtag", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_RosterEtag, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, rosterEtag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "otrEtag", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_OtrEtag, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, otrEtag), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "avatarHash", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_AvatarHash, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, avatarHash), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "vcardQueryStanzaId", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_VcardQueryStanzaId, + .hasIndex = 10, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, vcardQueryStanzaId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "capabilitiesExtFlags", + .dataTypeSpecific.className = NULL, + .number = GtalkPostAuthBatchQuery_FieldNumber_CapabilitiesExtFlags, + .hasIndex = 11, + .offset = (uint32_t)offsetof(GtalkPostAuthBatchQuery__storage_, capabilitiesExtFlags), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkPostAuthBatchQuery class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkPostAuthBatchQuery__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - Enum GtalkPostAuthBatchQuery_CapabilitiesExtFlags + +GPBEnumDescriptor *GtalkPostAuthBatchQuery_CapabilitiesExtFlags_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static const char *valueNames = + "HasVoiceV1\000HasVideoV1\000HasCameraV1\000HasPmu" + "cV1\000"; + static const int32_t values[] = { + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVoiceV1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVideoV1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasCameraV1, + GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasPmucV1, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GtalkPostAuthBatchQuery_CapabilitiesExtFlags) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GtalkPostAuthBatchQuery_CapabilitiesExtFlags_IsValidValue]; + if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GtalkPostAuthBatchQuery_CapabilitiesExtFlags_IsValidValue(int32_t value__) { + switch (value__) { + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVoiceV1: + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasVideoV1: + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasCameraV1: + case GtalkPostAuthBatchQuery_CapabilitiesExtFlags_HasPmucV1: + return YES; + default: + return NO; + } +} + +#pragma mark - GtalkStreamAck + +@implementation GtalkStreamAck + + +typedef struct GtalkStreamAck__storage_ { + uint32_t _has_storage_[1]; +} GtalkStreamAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkStreamAck class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GtalkStreamAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GtalkSelectiveAck + +@implementation GtalkSelectiveAck + +@dynamic idArray, idArray_Count; + +typedef struct GtalkSelectiveAck__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *idArray; +} GtalkSelectiveAck__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "idArray", + .dataTypeSpecific.className = NULL, + .number = GtalkSelectiveAck_FieldNumber_IdArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GtalkSelectiveAck__storage_, idArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GtalkSelectiveAck class] + rootClass:[GtalkGtalkExtensionsRoot class] + file:GtalkGtalkExtensionsRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GtalkSelectiveAck__storage_) + flags:GPBDescriptorInitializationFlag_None]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessaging.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessaging.h new file mode 100644 index 0000000..15caf8e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessaging.h @@ -0,0 +1,497 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * @related FIRMessaging + * + * The completion handler invoked when the registration token returns. + * If the call fails we return the appropriate `error code`, described by + * `FIRMessagingError`. + * + * @param FCMToken The valid registration token returned by FCM. + * @param error The error describing why a token request failed. The error code + * will match a value from the FIRMessagingError enumeration. + */ +typedef void(^FIRMessagingFCMTokenFetchCompletion)(NSString * _Nullable FCMToken, + NSError * _Nullable error) + NS_SWIFT_NAME(MessagingFCMTokenFetchCompletion); + + +/** + * @related FIRMessaging + * + * The completion handler invoked when the registration token deletion request is + * completed. If the call fails we return the appropriate `error code`, described + * by `FIRMessagingError`. + * + * @param error The error describing why a token deletion failed. The error code + * will match a value from the FIRMessagingError enumeration. + */ +typedef void(^FIRMessagingDeleteFCMTokenCompletion)(NSError * _Nullable error) + NS_SWIFT_NAME(MessagingDeleteFCMTokenCompletion); + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param error The error which occurred while updating the subscription topic + * on the FIRMessaging server. This will be nil in case the operation + * was successful, or if the operation was cancelled. + */ +typedef void (^FIRMessagingTopicOperationCompletion)(NSError *_Nullable error); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Notification sent when the upstream message has been delivered + * successfully to the server. The notification object will be the messageID + * of the successfully delivered message. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingSendSuccessNotification + NS_SWIFT_NAME(MessagingSendSuccess); + +/** + * Notification sent when the upstream message was failed to be sent to the + * server. The notification object will be the messageID of the failed + * message. The userInfo dictionary will contain the relevant error + * information for the failure. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingSendErrorNotification + NS_SWIFT_NAME(MessagingSendError); + +/** + * Notification sent when the Firebase messaging server deletes pending + * messages due to exceeded storage limits. This may occur, for example, when + * the device cannot be reached for an extended period of time. + * + * It is recommended to retrieve any missing messages directly from the + * server. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingMessagesDeletedNotification + NS_SWIFT_NAME(MessagingMessagesDeleted); + +/** + * Notification sent when Firebase Messaging establishes or disconnects from + * an FCM socket connection. You can query the connection state in this + * notification by checking the `isDirectChannelEstablished` property of FIRMessaging. + */ +FOUNDATION_EXPORT const NSNotificationName FIRMessagingConnectionStateChangedNotification + NS_SWIFT_NAME(MessagingConnectionStateChanged); + +/** + * Notification sent when the FCM registration token has been refreshed. Please use the + * FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and + * updated tokens. + */ +FOUNDATION_EXPORT const NSNotificationName + FIRMessagingRegistrationTokenRefreshedNotification + NS_SWIFT_NAME(MessagingRegistrationTokenRefreshed); +#else +/** + * Notification sent when the upstream message has been delivered + * successfully to the server. The notification object will be the messageID + * of the successfully delivered message. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingSendSuccessNotification + NS_SWIFT_NAME(MessagingSendSuccessNotification); + +/** + * Notification sent when the upstream message was failed to be sent to the + * server. The notification object will be the messageID of the failed + * message. The userInfo dictionary will contain the relevant error + * information for the failure. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingSendErrorNotification + NS_SWIFT_NAME(MessagingSendErrorNotification); + +/** + * Notification sent when the Firebase messaging server deletes pending + * messages due to exceeded storage limits. This may occur, for example, when + * the device cannot be reached for an extended period of time. + * + * It is recommended to retrieve any missing messages directly from the + * server. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingMessagesDeletedNotification + NS_SWIFT_NAME(MessagingMessagesDeletedNotification); + +/** + * Notification sent when Firebase Messaging establishes or disconnects from + * an FCM socket connection. You can query the connection state in this + * notification by checking the `isDirectChannelEstablished` property of FIRMessaging. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingConnectionStateChangedNotification + NS_SWIFT_NAME(MessagingConnectionStateChangedNotification); + +/** + * Notification sent when the FCM registration token has been refreshed. Please use the + * FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and + * updated tokens. + */ +FOUNDATION_EXPORT NSString *const FIRMessagingRegistrationTokenRefreshedNotification + NS_SWIFT_NAME(MessagingRegistrationTokenRefreshedNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @enum FIRMessagingError + */ +typedef NS_ENUM(NSUInteger, FIRMessagingError) { + /// Unknown error. + FIRMessagingErrorUnknown = 0, + + /// FIRMessaging couldn't validate request from this client. + FIRMessagingErrorAuthentication = 1, + + /// InstanceID service cannot be accessed. + FIRMessagingErrorNoAccess = 2, + + /// Request to InstanceID backend timed out. + FIRMessagingErrorTimeout = 3, + + /// No network available to reach the servers. + FIRMessagingErrorNetwork = 4, + + /// Another similar operation in progress, bailing this one. + FIRMessagingErrorOperationInProgress = 5, + + /// Some parameters of the request were invalid. + FIRMessagingErrorInvalidRequest = 7, + + /// Topic name is invalid for subscription/unsubscription. + FIRMessagingErrorInvalidTopicName = 8, + +} NS_SWIFT_NAME(MessagingError); + +/// Status for the downstream message received by the app. +typedef NS_ENUM(NSInteger, FIRMessagingMessageStatus) { + /// Unknown status. + FIRMessagingMessageStatusUnknown, + /// New downstream message received by the app. + FIRMessagingMessageStatusNew, +} NS_SWIFT_NAME(MessagingMessageStatus); + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * Firebase Messaging will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * Unless you really need to specify the type, you should use the `APNSToken` + * property instead. + */ +typedef NS_ENUM(NSInteger, FIRMessagingAPNSTokenType) { + /// Unknown token type. + FIRMessagingAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRMessagingAPNSTokenTypeSandbox, + /// Production token type. + FIRMessagingAPNSTokenTypeProd, +} NS_SWIFT_NAME(MessagingAPNSTokenType); + +/// Information about a downstream message received by the app. +NS_SWIFT_NAME(MessagingMessageInfo) +@interface FIRMessagingMessageInfo : NSObject + +/// The status of the downstream message +@property(nonatomic, readonly, assign) FIRMessagingMessageStatus status; + +@end + +/** + * A remote data message received by the app via FCM (not just the APNs interface). + * + * This is only for devices running iOS 10 or above. To support devices running iOS 9 or below, use + * the local and remote notifications handlers defined in UIApplicationDelegate protocol. + */ +NS_SWIFT_NAME(MessagingRemoteMessage) +@interface FIRMessagingRemoteMessage : NSObject + +/// The message ID of downstream message. +@property(nonatomic, readonly, copy) NSString *messageID; +/// The downstream message received by the application. +@property(nonatomic, readonly, strong) NSDictionary *appData; + +@end + +@class FIRMessaging; +@class FIRMessagingExtensionHelper; + +/** + * A protocol to handle token update or data message delivery from FCM. + * + */ +NS_SWIFT_NAME(MessagingDelegate) +@protocol FIRMessagingDelegate + +@optional +/// This method will be called once a token is available, or has been refreshed. Typically it +/// will be called once per app start, but may be called more often, if token is invalidated or +/// updated. In this method, you should perform operations such as: +/// +/// * Uploading the FCM token to your application server, so targeted notifications can be sent. +/// +/// * Subscribing to any topics. +- (void)messaging:(FIRMessaging *)messaging + didReceiveRegistrationToken:(NSString *)fcmToken + NS_SWIFT_NAME(messaging(_:didReceiveRegistrationToken:)); + +/// Handle data messages received via FCM direct channel (not via APNS). +- (void)messaging:(FIRMessaging *)messaging + didReceiveMessage:(FIRMessagingRemoteMessage *)remoteMessage +NS_SWIFT_NAME(messaging(_:didReceive:)); + +@end + +/** + * Firebase Messaging lets you reliably deliver messages at no cost. + * + * To send or receive messages, the app must get a + * registration token from FIRInstanceID. This token authorizes an + * app server to send messages to an app instance. + * + * In order to receive FIRMessaging messages, declare + * `application:didReceiveRemoteNotification::fetchCompletionHandler:`. + */ +NS_SWIFT_NAME(Messaging) +@interface FIRMessaging : NSObject + +/** + * Delegate to handle FCM token refreshes, and remote data messages received via FCM direct channel. + */ +@property(nonatomic, weak, nullable) id delegate; + +/** + * When set to `YES`, Firebase Messaging will automatically establish a socket-based, direct + * channel to the FCM server. Enable this only if you are sending upstream messages or + * receiving non-APNS, data-only messages in foregrounded apps. + * Default is `NO`. + */ +@property(nonatomic) BOOL shouldEstablishDirectChannel; + +/** + * Returns `YES` if the direct channel to the FCM server is active, and `NO` otherwise. + */ +@property(nonatomic, readonly) BOOL isDirectChannelEstablished; + +/** + * FIRMessaging + * + * @return An instance of FIRMessaging. + */ ++ (instancetype)messaging NS_SWIFT_NAME(messaging()); + +/** + * FIRMessagingExtensionHelper + * + * Use FIRMessagingExtensionHelper to populate rich UI contents for your notifications. + * e.g. If an image URL is set in your notification payload or on the console, call + * FIRMessagingExtensionHelper API to render it on your notification. + * + * @return An instance of FIRMessagingExtensionHelper that handles the extensions API. + */ ++ (FIRMessagingExtensionHelper *)extensionHelper NS_SWIFT_NAME(serviceExtension()) NS_AVAILABLE_IOS(10.0); + +/** + * Unavailable. Use +messaging instead. + */ +- (instancetype)init __attribute__((unavailable("Use +messaging instead."))); + +#pragma mark - APNS + +/** + * This property is used to set the APNS Token received by the application delegate. + * + * FIRMessaging uses method swizzling to ensure that the APNS token is set + * automatically. However, if you have disabled swizzling by setting + * `FirebaseAppDelegateProxyEnabled` to `NO` in your app's + * Info.plist, you should manually set the APNS token in your application + * delegate's `-application:didRegisterForRemoteNotificationsWithDeviceToken:` + * method. + * + * If you would like to set the type of the APNS token, rather than relying on + * automatic detection, see: `-setAPNSToken:type:`. + */ +@property(nonatomic, copy, nullable) NSData *APNSToken NS_SWIFT_NAME(apnsToken); + +/** + * Set APNS token for the application. This APNS token will be used to register + * with Firebase Messaging using `FCMToken` or + * `tokenWithAuthorizedEntity:scope:options:handler`. + * + * @param apnsToken The APNS token for the application. + * @param type The type of APNS token. Debug builds should use + * FIRMessagingAPNSTokenTypeSandbox. Alternatively, you can supply + * FIRMessagingAPNSTokenTypeUnknown to have the type automatically + * detected based on your provisioning profile. + */ +- (void)setAPNSToken:(NSData *)apnsToken type:(FIRMessagingAPNSTokenType)type; + +#pragma mark - FCM Tokens + +/** + * Is Firebase Messaging token auto generation enabled? If this flag is disabled, + * Firebase Messaging will not generate token automatically for message delivery. + * + * If this flag is disabled, Firebase Messaging does not generate new tokens automatically for + * message delivery. If this flag is enabled, FCM generates a registration token on application + * start when there is no existing valid token. FCM also generates a new token when an existing + * token is deleted. + * + * This setting is persisted, and is applied on future + * invocations of your application. Once explicitly set, it overrides any + * settings in your Info.plist. + * + * By default, FCM automatic initialization is enabled. If you need to change the + * default (for example, because you want to prompt the user before getting token) + * set FirebaseMessagingAutoInitEnabled to false in your application's Info.plist. + */ +@property(nonatomic, assign, getter=isAutoInitEnabled) BOOL autoInitEnabled; + +/** + * The FCM token is used to identify this device so that FCM can send notifications to it. + * It is associated with your APNS token when the APNS token is supplied, so that sending + * messages to the FCM token will be delivered over APNS. + * + * The FCM token is sometimes refreshed automatically. In your FIRMessaging delegate, the + * delegate method `messaging:didReceiveRegistrationToken:` will be called once a token is + * available, or has been refreshed. Typically it should be called once per app start, but + * may be called more often, if token is invalidated or updated. + * + * Once you have an FCM token, you should send it to your application server, so it can use + * the FCM token to send notifications to your device. + */ +@property(nonatomic, readonly, nullable) NSString *FCMToken NS_SWIFT_NAME(fcmToken); + + +/** + * Retrieves an FCM registration token for a particular Sender ID. This can be used to allow + * multiple senders to send notifications to the same device. By providing a different Sender + * ID than your default when fetching a token, you can create a new FCM token which you can + * give to a different sender. Both tokens will deliver notifications to your device, and you + * can revoke a token when you need to. + * + * This registration token is not cached by FIRMessaging. FIRMessaging should have an APNS + * token set before calling this to ensure that notifications can be delivered via APNS using + * this FCM token. You may re-retrieve the FCM token once you have the APNS token set, to + * associate it with the FCM token. The default FCM token is automatically associated with + * the APNS token, if the APNS token data is available. + * + * @param senderID The Sender ID for a particular Firebase project. + * @param completion The completion handler to handle the token request. + */ +- (void)retrieveFCMTokenForSenderID:(NSString *)senderID + completion:(FIRMessagingFCMTokenFetchCompletion)completion + NS_SWIFT_NAME(retrieveFCMToken(forSenderID:completion:)); + + +/** + * Invalidates an FCM token for a particular Sender ID. That Sender ID cannot no longer send + * notifications to that FCM token. + * + * @param senderID The senderID for a particular Firebase project. + * @param completion The completion handler to handle the token deletion. + */ +- (void)deleteFCMTokenForSenderID:(NSString *)senderID + completion:(FIRMessagingDeleteFCMTokenCompletion)completion + NS_SWIFT_NAME(deleteFCMToken(forSenderID:completion:)); + +#pragma mark - Topics + +/** + * Asynchronously subscribes to a topic. + * + * @param topic The name of the topic, for example, @"sports". + */ +- (void)subscribeToTopic:(NSString *)topic NS_SWIFT_NAME(subscribe(toTopic:)); + +/** + * Asynchronously subscribe to the provided topic, retrying on failure. + * + * @param topic The topic name to subscribe to, for example, @"sports". + * @param completion The completion that is invoked once the subscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)subscribeToTopic:(nonnull NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion; + +/** + * Asynchronously unsubscribe from a topic. + * + * @param topic The name of the topic, for example @"sports". + */ +- (void)unsubscribeFromTopic:(NSString *)topic NS_SWIFT_NAME(unsubscribe(fromTopic:)); + +/** + * Asynchronously unsubscribe from the provided topic, retrying on failure. + * + * @param topic The topic name to unsubscribe from, for example @"sports". + * @param completion The completion that is invoked once the unsubscribe call ends. + * In case of success, nil error is returned. Otherwise, an + * appropriate error object is returned. + */ +- (void)unsubscribeFromTopic:(nonnull NSString *)topic + completion:(nullable FIRMessagingTopicOperationCompletion)completion; + +#pragma mark - Upstream + +/** + * Sends an upstream ("device to cloud") message. + * + * The message is queued if we don't have an active connection. + * You can only use the upstream feature if your FCM implementation + * uses the XMPP server protocol. + * + * @param message Key/Value pairs to be sent. Values must be String, any + * other type will be ignored. + * @param receiver A string identifying the receiver of the message. For FCM + * project IDs the value is `SENDER_ID@gcm.googleapis.com`. + * @param messageID The ID of the message. This is generated by the application. It + * must be unique for each message generated by this application. + * It allows error callbacks and debugging, to uniquely identify + * each message. + * @param ttl The time to live for the message. In case we aren't able to + * send the message before the TTL expires we will send you a + * callback. If 0, we'll attempt to send immediately and return + * an error if we're not connected. Otherwise, the message will + * be queued. As for server-side messages, we don't return an error + * if the message has been dropped because of TTL; this can happen + * on the server side, and it would require extra communication. + */ +- (void)sendMessage:(NSDictionary *)message + to:(NSString *)receiver + withMessageID:(NSString *)messageID + timeToLive:(int64_t)ttl; + +#pragma mark - Analytics + +/** + * Use this to track message delivery and analytics for messages, typically + * when you receive a notification in `application:didReceiveRemoteNotification:`. + * However, you only need to call this if you set the `FirebaseAppDelegateProxyEnabled` + * flag to `NO` in your Info.plist. If `FirebaseAppDelegateProxyEnabled` is either missing + * or set to `YES` in your Info.plist, the library will call this automatically. + * + * @param message The downstream message received by the application. + * + * @return Information about the downstream message. + */ +- (FIRMessagingMessageInfo *)appDidReceiveMessage:(NSDictionary *)message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessagingExtensionHelper.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessagingExtensionHelper.h new file mode 100644 index 0000000..f50478e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FIRMessagingExtensionHelper.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +#import +#endif + + NS_ASSUME_NONNULL_BEGIN + + __IOS_AVAILABLE(10.0) +@interface FIRMessagingExtensionHelper : NSObject + + /// Call this API to complete your notification content modification. If you like to +/// overwrite some properties of the content instead of using the default payload, +/// make sure to make your customized motification to the content before passing it to +/// this call. +- (void)populateNotificationContent:(UNMutableNotificationContent *)content + withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler; + + @end + + NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FirebaseMessaging.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FirebaseMessaging.h new file mode 100755 index 0000000..c5d0bd0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/Firebase/Messaging/Public/FirebaseMessaging.h @@ -0,0 +1,18 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMessaging.h" +#import "FIRMessagingExtensionHelper.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/FirebaseMessaging/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement new file mode 100755 index 0000000..2561d1a Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap new file mode 100755 index 0000000..b66fb64 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap @@ -0,0 +1,10 @@ +framework module GoogleAppMeasurement { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m new file mode 100644 index 0000000..abffc3e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m @@ -0,0 +1,1034 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TargetConditionals.h" + +#if TARGET_OS_IOS || TARGET_OS_TV + +#import +#import +#import +#import "../Common/GULLoggerCodes.h" +#import "Internal/GULAppDelegateSwizzler_Private.h" +#import "Private/GULAppDelegateSwizzler.h" + +#import +#import + +// Implementations need to be typed before calling the implementation directly to cast the +// arguments and the return types correctly. Otherwise, it will crash the app. +typedef BOOL (*GULRealOpenURLSourceApplicationAnnotationIMP)( + id, SEL, UIApplication *, NSURL *, NSString *, id); + +typedef BOOL (*GULRealOpenURLOptionsIMP)( + id, SEL, UIApplication *, NSURL *, NSDictionary *); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)( + id, SEL, UIApplication *, NSString *, void (^)()); +#pragma clang diagnostic pop + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef BOOL (*GULRealContinueUserActivityIMP)( + id, SEL, UIApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects)); +#pragma clang diagnostic pop + +typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, UIApplication *, NSData *); + +typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id, + SEL, + UIApplication *, + NSError *); + +typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, UIApplication *, NSDictionary *); + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +// This is needed to for the library to be warning free on iOS versions < 7. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)( + id, SEL, UIApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)); +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + +typedef void (^GULAppDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; + +static NSString *const kGULAppDelegateKeyPath = @"delegate"; + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/AppDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App Delegate Proxying. */ +static NSString *const kGULFirebaseAppDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App Delegate Proxying. */ +static NSString *const kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the App Delegate. */ +static NSString *const kGULAppDelegatePrefix = @"GUL_"; + +/** The original instance of App Delegate. */ +static id gOriginalAppDelegate; + +/** The original App Delegate class */ +static Class gOriginalAppDelegateClass; + +/** The subclass of the original App Delegate. */ +static Class gAppDelegateSubclass; + +/** Remote notification methods selectors + * + * We have to opt out of referencing APNS related App Delegate methods directly to prevent + * an Apple review warning email about missing Push Notification Entitlement + * (like here: https://github.com/firebase/firebase-ios-sdk/issues/2807). From our experience, the + * warning is triggered when any of the symbols is present in the application sent to review, even + * if the code is never executed. Because GULAppDelegateSwizzler may be used by applications that + * are not using APNS we have to refer to the methods indirectly using selector constructed from + * string. + * + * NOTE: None of the methods is proxied unless it is explicitly requested by calling the method + * +[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods] + */ +static NSString *const kGULDidRegisterForRemoteNotificationsSEL = + @"application:didRegisterForRemoteNotificationsWithDeviceToken:"; +static NSString *const kGULDidFailToRegisterForRemoteNotificationsSEL = + @"application:didFailToRegisterForRemoteNotificationsWithError:"; +static NSString *const kGULDidReceiveRemoteNotificationSEL = + @"application:didReceiveRemoteNotification:"; +static NSString *const kGULDidReceiveRemoteNotificationWithCompletionSEL = + @"application:didReceiveRemoteNotification:fetchCompletionHandler:"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULZeroingWeakContainer +@end + +@interface GULAppDelegateObserver : NSObject +@end + +@implementation GULAppDelegateObserver { + BOOL _isObserving; +} + ++ (GULAppDelegateObserver *)sharedInstance { + static GULAppDelegateObserver *instance; + static dispatch_once_t once; + dispatch_once(&once, ^{ + instance = [[GULAppDelegateObserver alloc] init]; + }); + return instance; +} + +- (void)observeUIApplication { + if (_isObserving) { + return; + } + [[GULAppDelegateSwizzler sharedApplication] + addObserver:self + forKeyPath:kGULAppDelegateKeyPath + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:nil]; + _isObserving = YES; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqual:kGULAppDelegateKeyPath]) { + id newValue = change[NSKeyValueChangeNewKey]; + id oldValue = change[NSKeyValueChangeOldKey]; + if ([newValue isEqual:oldValue]) { + return; + } + // Free the stored app delegate instance because it has been changed to a different instance to + // avoid keeping it alive forever. + if ([oldValue isEqual:gOriginalAppDelegate]) { + gOriginalAppDelegate = nil; + // Remove the observer. Parse it to NSObject to avoid warning. + [[GULAppDelegateSwizzler sharedApplication] removeObserver:self + forKeyPath:kGULAppDelegateKeyPath]; + _isObserving = NO; + } + } +} + +@end + +@implementation GULAppDelegateSwizzler + +static dispatch_once_t sProxyAppDelegateOnceToken; +static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; + +#pragma mark - Public methods + ++ (BOOL)isAppDelegateProxyEnabled { + NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; + + id isFirebaseProxyEnabledPlistValue = infoDictionary[kGULFirebaseAppDelegateProxyEnabledPlistKey]; + id isGoogleProxyEnabledPlistValue = + infoDictionary[kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey]; + + // Enabled by default. + BOOL isFirebaseAppDelegateProxyEnabled = YES; + BOOL isGoogleUtilitiesAppDelegateProxyEnabled = YES; + + if ([isFirebaseProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isFirebaseAppDelegateProxyEnabled = [isFirebaseProxyEnabledPlistValue boolValue]; + } + + if ([isGoogleProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isGoogleUtilitiesAppDelegateProxyEnabled = [isGoogleProxyEnabledPlistValue boolValue]; + } + + // Only deactivate the proxy if it is explicitly disabled by app developers using either one of + // the plist flags. + return isFirebaseAppDelegateProxyEnabled && isGoogleUtilitiesAppDelegateProxyEnabled; +} + ++ (GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor { + NSAssert(interceptor, @"AppDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(UIApplicationDelegate)], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling000], + @"AppDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(UIApplicationDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling001], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = [NSString stringWithFormat:@"%@%p", kGULAppDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling002], + @"AppDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULZeroingWeakContainer *weakObject = [[GULZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULAppDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"AppDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"AppDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling003], + @"AppDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULZeroingWeakContainer *weakContainer = [GULAppDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling004], + @"AppDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + ++ (void)proxyOriginalDelegate { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + dispatch_once(&sProxyAppDelegateOnceToken, ^{ + id originalDelegate = + [GULAppDelegateSwizzler sharedApplication].delegate; + [GULAppDelegateSwizzler proxyAppDelegate:originalDelegate]; + }); +} + ++ (void)proxyOriginalDelegateIncludingAPNSMethods { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + [self proxyOriginalDelegate]; + + dispatch_once(&sProxyAppDelegateRemoteNotificationOnceToken, ^{ + id appDelegate = [GULAppDelegateSwizzler sharedApplication].delegate; + + NSMutableDictionary *realImplementationsBySelector = + [objc_getAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey) mutableCopy]; + + [self proxyRemoteNotificationsMethodsWithAppDelegateSubClass:gAppDelegateSubclass + realClass:gOriginalAppDelegateClass + appDelegate:appDelegate + realImplementationsBySelector:realImplementationsBySelector]; + + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN); + [self reassignAppDelegate]; + }); +} + +#pragma mark - Create proxy + ++ (UIApplication *)sharedApplication { + if ([GULAppEnvironmentUtil isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - Override default methods + +/** Creates a new subclass of the class of the given object and sets the isa value of the given + * object to the new subclass. Additionally this copies methods to that new subclass that allow us + * to intercept UIApplicationDelegate methods. This is better known as isa swizzling. + * + * @param appDelegate The object to which you want to isa swizzle. This has to conform to the + * UIApplicationDelegate subclass. + * @return Returns the new subclass. + */ ++ (nullable Class)createSubclassWithObject:(id)appDelegate { + Class realClass = [appDelegate class]; + + // Create GUL__ + NSString *classNameWithPrefix = + [kGULAppDelegatePrefix stringByAppendingString:NSStringFromClass(realClass)]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling005], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: %@", + NSStringFromClass(realClass), newClassName); + return nil; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class appDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (appDelegateSubClass == Nil) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling006], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: Nil", + NSStringFromClass(realClass)); + return nil; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // Add the following methods from GULAppDelegate class, and store the real implementation so it + // can forward to the real one. + // For application:openURL:options: + SEL applicationOpenURLOptionsSEL = @selector(application:openURL:options:); + if ([appDelegate respondsToSelector:applicationOpenURLOptionsSEL]) { + // Only add the application:openURL:options: method if the original AppDelegate implements it. + // This fixes a bug if an app only implements application:openURL:sourceApplication:annotation: + // (if we add the `options` method, iOS sees that one exists and does not call the + // `sourceApplication` method, which in this case is the only one the app implements). + + [self proxyDestinationSelector:applicationOpenURLOptionsSEL + implementationsFromSourceSelector:applicationOpenURLOptionsSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + + // For application:continueUserActivity:restorationHandler: + SEL continueUserActivitySEL = @selector(application:continueUserActivity:restorationHandler:); + [self proxyDestinationSelector:continueUserActivitySEL + implementationsFromSourceSelector:continueUserActivitySEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:handleEventsForBackgroundURLSession:completionHandler: + SEL handleEventsForBackgroundURLSessionSEL = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + [self proxyDestinationSelector:handleEventsForBackgroundURLSessionSEL + implementationsFromSourceSelector:handleEventsForBackgroundURLSessionSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + +#if TARGET_OS_IOS + // For application:openURL:sourceApplication:annotation: + SEL openURLSourceApplicationAnnotationSEL = @selector(application: + openURL:sourceApplication:annotation:); + + [self proxyDestinationSelector:openURLSourceApplicationAnnotationSEL + implementationsFromSourceSelector:openURLSourceApplicationAnnotationSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS + + // Override the description too so the custom class name will not show up. + [GULAppDelegateSwizzler addInstanceMethodWithDestinationSelector:@selector(description) + withImplementationFromSourceSelector:@selector(fakeDescription) + fromClass:[self class] + toClass:appDelegateSubClass]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(appDelegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(appDelegateSubClass)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling007], + @"Cannot create subclass of App Delegate, because the created subclass is not the " + @"same size. %@", + NSStringFromClass(realClass)); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return nil; + } + + // Make the newly created class to be the subclass of the real App Delegate class. + objc_registerClassPair(appDelegateSubClass); + if (object_setClass(appDelegate, appDelegateSubClass)) { + GULLogDebug(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling008], + @"Successfully created App Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULAppDelegateSwizzler correctAppDelegateProxyKey]); + } + + return appDelegateSubClass; +} + ++ (void)proxyRemoteNotificationsMethodsWithAppDelegateSubClass:(Class)appDelegateSubClass + realClass:(Class)realClass + appDelegate:(id)appDelegate + realImplementationsBySelector: + (NSMutableDictionary *)realImplementationsBySelector { + if (realClass == nil || appDelegateSubClass == nil || appDelegate == nil || + realImplementationsBySelector == nil) { + // The App Delegate has not been swizzled. + return; + } + + // For application:didRegisterForRemoteNotificationsWithDeviceToken: + SEL didRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + SEL didRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didRegisterForRemoteNotificationsWithDeviceToken:); + + [self proxyDestinationSelector:didRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didFailToRegisterForRemoteNotificationsWithError: + SEL didFailToRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + SEL didFailToRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didFailToRegisterForRemoteNotificationsWithError:); + + [self proxyDestinationSelector:didFailToRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didFailToRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification: + SEL didReceiveRemoteNotificationSEL = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + SEL didReceiveRemoteNotificationDonotSEL = @selector(application: + donor_didReceiveRemoteNotification:); + + [self proxyDestinationSelector:didReceiveRemoteNotificationSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationDonotSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification:fetchCompletionHandler: +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + if ([GULAppEnvironmentUtil isIOS7OrHigher]) { + SEL didReceiveRemoteNotificationWithCompletionSEL = + NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + SEL didReceiveRemoteNotificationWithCompletionDonorSEL = + @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); + if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { + // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if + // the original AppDelegate implements it. + // This fixes a bug if an app only implements application:didReceiveRemoteNotification: + // (if we add the method with completion, iOS sees that one exists and does not call + // the method without the completion, which in this case is the only one the app implements). + + [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + } +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +} + +/// We have to do this to invalidate the cache that caches the original respondsToSelector of +/// openURL handlers. Without this, it won't call the default implementations because the system +/// checks and caches them. +/// Register KVO only once. Otherwise, the observing method will be called as many times as +/// being registered. ++ (void)reassignAppDelegate { + id delegate = [self sharedApplication].delegate; + [self sharedApplication].delegate = nil; + [self sharedApplication].delegate = delegate; + gOriginalAppDelegate = delegate; + [[GULAppDelegateObserver sharedInstance] observeUIApplication]; +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULAppDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULAppDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULAppDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULAppDelegateInterceptorCallback)callback { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULAppDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeAppDelegateSwizzling010], + @"AppDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + +// The methods below are donor methods which are added to the dynamic subclass of the App Delegate. +// They are called within the scope of the real App Delegate so |self| does not refer to the +// GULAppDelegateSwizzler instance but the real App Delegate instance. + +#pragma mark - [Donor Methods] Overridden instance description method + +- (NSString *)fakeDescription { + Class realClass = objc_getAssociatedObject(self, &kGULRealClassKey); + return [NSString stringWithFormat:@"<%@: %p>", realClass, self]; +} + +#pragma mark - [Donor Methods] URL overridden handler methods + +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options { + SEL methodSelector = @selector(application:openURL:options:); + // Call the real implementation if the real App Delegate has any. + NSValue *openURLIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLOptionsIMP openURLOptionsIMP = [openURLIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + +// This is needed to for the library to be warning free on iOS versions < 9. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + openURL:url + options:options]; + }]; +#pragma clang diagnostic pop + if (openURLOptionsIMP) { + returnedValue |= openURLOptionsIMP(self, methodSelector, application, url, options); + } + return returnedValue; +} + +#if TARGET_OS_IOS + +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + sourceApplication:(NSString *)sourceApplication + annotation:(id)annotation { + SEL methodSelector = @selector(application:openURL:sourceApplication:annotation:); + + // Call the real implementation if the real App Delegate has any. + NSValue *openURLSourceAppAnnotationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLSourceApplicationAnnotationIMP openURLSourceApplicationAnnotationIMP = + [openURLSourceAppAnnotationIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + returnedValue |= [interceptor application:application + openURL:url + sourceApplication:sourceApplication + annotation:annotation]; +#pragma clang diagnostic pop + }]; + if (openURLSourceApplicationAnnotationIMP) { + returnedValue |= openURLSourceApplicationAnnotationIMP(self, methodSelector, application, url, + sourceApplication, annotation); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS + +#pragma mark - [Donor Methods] Network overridden handler methods + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +- (void)application:(UIApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(void (^)())completionHandler API_AVAILABLE(ios(7.0)) { +#pragma clang diagnostic pop + SEL methodSelector = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + NSValue *handleBackgroundSessionPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealHandleEventsForBackgroundURLSessionIMP handleBackgroundSessionIMP = + [handleBackgroundSessionPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + [interceptor application:application + handleEventsForBackgroundURLSession:identifier + completionHandler:completionHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (handleBackgroundSessionIMP) { + handleBackgroundSessionIMP(self, methodSelector, application, identifier, completionHandler); + } +} + +#pragma mark - [Donor Methods] User Activities overridden handler methods + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (BOOL)application:(UIApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { + SEL methodSelector = @selector(application:continueUserActivity:restorationHandler:); + NSValue *continueUserActivityIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealContinueUserActivityIMP continueUserActivityIMP = + continueUserActivityIMPPointer.pointerValue; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + continueUserActivity:userActivity + restorationHandler:restorationHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (continueUserActivityIMP) { + returnedValue |= continueUserActivityIMP(self, methodSelector, application, userActivity, + restorationHandler); + } + return returnedValue; +} +#pragma clang diagnostic pop + +#pragma mark - [Donor Methods] Remote Notifications + +- (void)application:(UIApplication *)application + donor_didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + SEL methodSelector = NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + + NSValue *didRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidRegisterForRemoteNotificationsIMP didRegisterForRemoteNotificationsIMP = + [didRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&deviceToken) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didRegisterForRemoteNotificationsIMP) { + didRegisterForRemoteNotificationsIMP(self, methodSelector, application, deviceToken); + } +} + +- (void)application:(UIApplication *)application + donor_didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + SEL methodSelector = NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + NSValue *didFailToRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidFailToRegisterForRemoteNotificationsIMP didFailToRegisterForRemoteNotificationsIMP = + [didFailToRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&error) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didFailToRegisterForRemoteNotificationsIMP) { + didFailToRegisterForRemoteNotificationsIMP(self, methodSelector, application, error); + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +// This is needed to for the library to be warning free on iOS versions < 7. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (void)application:(UIApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + NSValue *didReceiveRemoteNotificationWithCompletionIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationWithCompletionIMP + didReceiveRemoteNotificationWithCompletionIMP = + [didReceiveRemoteNotificationWithCompletionIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation setArgument:(void *)(&completionHandler) atIndex:4]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationWithCompletionIMP) { + didReceiveRemoteNotificationWithCompletionIMP(self, methodSelector, application, userInfo, + completionHandler); + } +} +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + +- (void)application:(UIApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + NSValue *didReceiveRemoteNotificationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationIMP didReceiveRemoteNotificationIMP = + [didReceiveRemoteNotificationIMPPointer pointerValue]; + + // Notify interceptors. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation invoke]; + }]; +#pragma clang diagnostic pop + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationIMP) { + didReceiveRemoteNotificationIMP(self, methodSelector, application, userInfo); + } +} + ++ (nullable NSInvocation *)appDelegateInvocationForSelector:(SEL)selector { + struct objc_method_description methodDescription = + protocol_getMethodDescription(@protocol(UIApplicationDelegate), selector, NO, YES); + if (methodDescription.types == NULL) { + return nil; + } + + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + return [NSInvocation invocationWithMethodSignature:signature]; +} + ++ (void)proxyAppDelegate:(id)appDelegate { + if (![appDelegate conformsToProtocol:@protocol(UIApplicationDelegate)]) { + GULLogNotice( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate], + @"App Delegate does not conform to UIApplicationDelegate protocol. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + id originalDelegate = appDelegate; + // Do not create a subclass if it is not enabled. + if (![GULAppDelegateSwizzler isAppDelegateProxyEnabled]) { + GULLogNotice(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling011], + @"App Delegate Proxy is disabled. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + // Do not accept nil delegate. + if (!originalDelegate) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling012], + @"Cannot create App Delegate Proxy because App Delegate instance is nil. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + @try { + gOriginalAppDelegateClass = [originalDelegate class]; + gAppDelegateSubclass = [self createSubclassWithObject:originalDelegate]; + [self reassignAppDelegate]; + } @catch (NSException *exception) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling013], + @"Cannot create App Delegate Proxy. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } +} + +#pragma mark - Methods to print correct debug logs + ++ (NSString *)correctAppDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseAppDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey; +} + ++ (NSString *)correctAlternativeWhenAppDelegateProxyNotCreated { + return NSClassFromString(@"FIRCore") + ? @"To log deep link campaigns manually, call the methods in " + @"FIRAnalytics+AppDelegate.h." + : @""; +} + +#pragma mark - Private Methods for Testing + +#ifdef GUL_APP_DELEGATE_TESTING + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (void)resetProxyOriginalDelegateOnceToken { + sProxyAppDelegateOnceToken = 0; + sProxyAppDelegateRemoteNotificationOnceToken = 0; +} + ++ (id)originalDelegate { + return gOriginalAppDelegate; +} + +#endif // GUL_APP_DELEGATE_TESTING + +@end + +#endif // TARGET_OS_IOS || TARGET_OS_TV diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h new file mode 100644 index 0000000..6e6b556 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class UIApplication; + +NS_ASSUME_NONNULL_BEGIN + +@interface GULAppDelegateSwizzler () + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param appDelegate The object that needs to be isa swizzled. This should conform to the + * UIApplicationDelegate protocol. + */ ++ (void)proxyAppDelegate:(id)appDelegate; + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +#ifdef GUL_APP_DELEGATE_TESTING // Methods only used in tests. + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** Resets the token that prevents the app delegate proxy from being isa swizzled multiple times. */ ++ (void)resetProxyOriginalDelegateOnceToken; + +/** Returns the original app delegate that was proxied. + * + * @return The original app delegate instance that was proxied. + */ ++ (id)originalDelegate; + +#endif // GUL_APP_DELEGATE_TESTING + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h new file mode 100644 index 0000000..d861ed1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class UIApplication; +@protocol UIApplicationDelegate; + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULAppDelegateInterceptorID; + +/** This class contains methods that isa swizzle the app delegate. */ +@interface GULAppDelegateSwizzler : NSProxy + +/** Registers an app delegate interceptor whose methods will be invoked as they're invoked on the + * original app delegate. + * + * @param interceptor An instance of a class that conforms to the UIApplicationDelegate protocol. + * The interceptor is NOT retained. + * @return A unique GULAppDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor; + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID; + +/** This method ensures that the original app delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the app delegate once). + * + * This method doesn't proxy APNS related methods: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * To proxy these methods use +[GULAppDelegateSwizzler + * proxyOriginalDelegateIncludingAPNSMethods]. The methods have to be proxied separately to + * avoid potential warnings from Apple review about missing Push Notification Entitlement (e.g. + * https://github.com/firebase/firebase-ios-sdk/issues/2807) + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegateIncludingAPNSMethods + */ ++ (void)proxyOriginalDelegate; + +/** This method ensures that the original app delegate has been proxied including APNS related + * methods. Call this before registering your interceptor. This method is safe to call multiple + * times (but it only proxies the app delegate once) or + * after +[GULAppDelegateSwizzler proxyOriginalDelegate] + * + * This method calls +[GULAppDelegateSwizzler proxyOriginalDelegate] under the hood. + * After calling this method the following App Delegate methods will be proxied in addition to + * the methods proxied by proxyOriginalDelegate: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegate + */ ++ (void)proxyOriginalDelegateIncludingAPNSMethods; + +/** Indicates whether app delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if AppDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isAppDelegateProxyEnabled; + +/** Returns the current sharedApplication. + * + * @return the current UIApplication if in an app, or nil if in extension or if it doesn't exist. + */ ++ (nullable UIApplication *)sharedApplication; + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +NS_ASSUME_NONNULL_END + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h new file mode 100644 index 0000000..fd22ba6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +typedef NS_ENUM(NSInteger, GULSwizzlerMessageCode) { + // App Delegate Swizzling. + kGULSwizzlerMessageCodeAppDelegateSwizzling000 = 1000, // I-SWZ001000 + kGULSwizzlerMessageCodeAppDelegateSwizzling001 = 1001, // I-SWZ001001 + kGULSwizzlerMessageCodeAppDelegateSwizzling002 = 1002, // I-SWZ001002 + kGULSwizzlerMessageCodeAppDelegateSwizzling003 = 1003, // I-SWZ001003 + kGULSwizzlerMessageCodeAppDelegateSwizzling004 = 1004, // I-SWZ001004 + kGULSwizzlerMessageCodeAppDelegateSwizzling005 = 1005, // I-SWZ001005 + kGULSwizzlerMessageCodeAppDelegateSwizzling006 = 1006, // I-SWZ001006 + kGULSwizzlerMessageCodeAppDelegateSwizzling007 = 1007, // I-SWZ001007 + kGULSwizzlerMessageCodeAppDelegateSwizzling008 = 1008, // I-SWZ001008 + kGULSwizzlerMessageCodeAppDelegateSwizzling009 = 1009, // I-SWZ001009 + kGULSwizzlerMessageCodeAppDelegateSwizzling010 = 1010, // I-SWZ001010 + kGULSwizzlerMessageCodeAppDelegateSwizzling011 = 1011, // I-SWZ001011 + kGULSwizzlerMessageCodeAppDelegateSwizzling012 = 1012, // I-SWZ001012 + kGULSwizzlerMessageCodeAppDelegateSwizzling013 = 1013, // I-SWZ001013 + kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate = 1014, // I-SWZ001014 + + // Method Swizzling. + kGULSwizzlerMessageCodeMethodSwizzling000 = 2000, // I-SWZ002000 +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h new file mode 100644 index 0000000..d550264 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GULAppEnvironmentUtil : NSObject + +/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, +/// development environment or sideloaded. ++ (BOOL)isFromAppStore; + +/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. +/// Returns NO otherwise. ++ (BOOL)isAppStoreReceiptSandbox; + +/// Indicates whether the app is on simulator or not at runtime depending on the device +/// architecture. ++ (BOOL)isSimulator; + +/// The current device model. Returns an empty string if device model cannot be retrieved. ++ (NSString *)deviceModel; + +/// The current operating system version. Returns an empty string if the system version cannot be +/// retrieved. ++ (NSString *)systemVersion; + +/// Indicates whether it is running inside an extension or an app. ++ (BOOL)isAppExtension; + +/// @return Returns @YES when is run on iOS version greater or equal to 7.0 ++ (BOOL)isIOS7OrHigher; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m new file mode 100644 index 0000000..8327438 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m @@ -0,0 +1,262 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GULAppEnvironmentUtil.h" + +#import +#import +#import +#import + +#if TARGET_OS_IOS +#import +#endif + +/// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from +/// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just +/// provide the definitions here. +#if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO) +#define LC_ENCRYPTION_INFO 0x21 +struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; +}; +#endif + +@implementation GULAppEnvironmentUtil + +/// A key for the Info.plist to enable or disable checking if the App Store is running in a sandbox. +/// This will affect your data integrity when using Firebase Analytics, as it will disable some +/// necessary checks. +static NSString *const kFIRAppStoreReceiptURLCheckEnabledKey = + @"FirebaseAppStoreReceiptURLCheckEnabled"; + +/// The file name of the sandbox receipt. This is available on iOS >= 8.0 +static NSString *const kFIRAIdentitySandboxReceiptFileName = @"sandboxReceipt"; + +/// The following copyright from Landon J. Fuller applies to the isAppEncrypted function. +/// +/// Copyright (c) 2017 Landon J. Fuller +/// All rights reserved. +/// +/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +/// and associated documentation files (the "Software"), to deal in the Software without +/// restriction, including without limitation the rights to use, copy, modify, merge, publish, +/// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +/// Software is furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in all copies or +/// substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +/// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +/// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/// +/// Comment from iPhone Dev Wiki +/// Crack Prevention: +/// App Store binaries are signed by both their developer and Apple. This encrypts the binary so +/// that decryption keys are needed in order to make the binary readable. When iOS executes the +/// binary, the decryption keys are used to decrypt the binary into a readable state where it is +/// then loaded into memory and executed. iOS can tell the encryption status of a binary via the +/// cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is a non-zero +/// value then the binary is encrypted. +/// +/// 'Cracking' works by letting the kernel decrypt the binary then siphoning the decrypted data into +/// a new binary file, resigning, and repackaging. This will only work on jailbroken devices as +/// codesignature validation has been removed. Resigning takes place because while the codesignature +/// doesn't have to be valid thanks to the jailbreak, it does have to be in place unless you have +/// AppSync or similar to disable codesignature checks. +/// +/// More information at Landon Fuller's blog +static BOOL IsAppEncrypted() { + const struct mach_header *executableHeader = NULL; + for (uint32_t i = 0; i < _dyld_image_count(); i++) { + const struct mach_header *header = _dyld_get_image_header(i); + if (header && header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + + if (!executableHeader) { + return NO; + } + + BOOL is64bit = (executableHeader->magic == MH_MAGIC_64); + uintptr_t cursor = (uintptr_t)executableHeader + + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header)); + const struct segment_command *segmentCommand = NULL; + uint32_t i = 0; + + while (i++ < executableHeader->ncmds) { + segmentCommand = (struct segment_command *)cursor; + + if (!segmentCommand) { + continue; + } + + if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) || + (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) { + if (is64bit) { + struct encryption_info_command_64 *cryptCmd = + (struct encryption_info_command_64 *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } else { + struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } + } + cursor += segmentCommand->cmdsize; + } + + return NO; +} + +static BOOL HasSCInfoFolder() { +#if TARGET_OS_IOS || TARGET_OS_TV + NSString *bundlePath = [NSBundle mainBundle].bundlePath; + NSString *scInfoPath = [bundlePath stringByAppendingPathComponent:@"SC_Info"]; + return [[NSFileManager defaultManager] fileExistsAtPath:scInfoPath]; +#elif TARGET_OS_OSX + return NO; +#endif +} + +static BOOL HasEmbeddedMobileProvision() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"].length > 0; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isFromAppStore { + static dispatch_once_t isEncryptedOnce; + static BOOL isEncrypted = NO; + + dispatch_once(&isEncryptedOnce, ^{ + isEncrypted = IsAppEncrypted(); + }); + + if ([GULAppEnvironmentUtil isSimulator]) { + return NO; + } + + // If an app contain the sandboxReceipt file, it means its coming from TestFlight + // This must be checked before the SCInfo Folder check below since TestFlight apps may + // also have an SCInfo folder. + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox]) { + return NO; + } + + if (HasSCInfoFolder()) { + // When iTunes downloads a .ipa, it also gets a customized .sinf file which is added to the + // main SC_Info directory. + return YES; + } + + // For iOS >= 8.0, iTunesMetadata.plist is moved outside of the sandbox. Any attempt to read + // the iTunesMetadata.plist outside of the sandbox will be rejected by Apple. + // If the app does not contain the embedded.mobileprovision which is stripped out by Apple when + // the app is submitted to store, then it is highly likely that it is from Apple Store. + return isEncrypted && !HasEmbeddedMobileProvision(); +} + ++ (BOOL)isAppStoreReceiptSandbox { + // Since checking the App Store's receipt URL can be memory intensive, check the option in the + // Info.plist if developers opted out of this check. + id enableSandboxCheck = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRAppStoreReceiptURLCheckEnabledKey]; + if (enableSandboxCheck && [enableSandboxCheck isKindOfClass:[NSNumber class]] && + ![enableSandboxCheck boolValue]) { + return NO; + } +// The #else is for pre Xcode 9 where @available is not yet implemented. +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; + NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; + return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; + } + return NO; +} + ++ (BOOL)isSimulator { +#if TARGET_OS_IOS || TARGET_OS_TV + NSString *platform = [GULAppEnvironmentUtil deviceModel]; + return [platform isEqual:@"x86_64"] || [platform isEqual:@"i386"]; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (NSString *)deviceModel { + static dispatch_once_t once; + static NSString *deviceModel; + + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + deviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return deviceModel; +} + ++ (NSString *)systemVersion { +#if TARGET_OS_IOS + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_TV + // Assemble the systemVersion, excluding the patch version if it's 0. + NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; + NSMutableString *versionString = [[NSMutableString alloc] + initWithFormat:@"%ld.%ld", (long)osVersion.majorVersion, (long)osVersion.minorVersion]; + if (osVersion.patchVersion != 0) { + [versionString appendFormat:@".%ld", (long)osVersion.patchVersion]; + } + return versionString; +#endif +} + ++ (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV + // Documented by Apple + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isIOS7OrHigher { +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + return YES; + } + + return NO; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m new file mode 100644 index 0000000..495e583 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m @@ -0,0 +1,209 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULLogger.h" + +#include + +#import +#import "Public/GULLoggerLevel.h" + +/// ASL client facility name used by GULLogger. +const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; + +static dispatch_once_t sGULLoggerOnceToken; + +static aslclient sGULLoggerClient; + +static dispatch_queue_t sGULClientQueue; + +static BOOL sGULLoggerDebugMode; + +static GULLoggerLevel sGULLoggerMaximumLevel; + +// Allow clients to register a version to include in the log. +static const char *sVersion = ""; + +static GULLoggerService kGULLoggerLogger = @"[GULLogger]"; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void GULLoggerInitializeASL(void) { + dispatch_once(&sGULLoggerOnceToken, ^{ + NSInteger majorOSVersion = [[GULAppEnvironmentUtil systemVersion] integerValue]; + uint32_t aslOptions = ASL_OPT_STDERR; +#if TARGET_OS_SIMULATOR + // The iOS 11 simulator doesn't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 11) { + aslOptions = 0; + } +#else + // Devices running iOS 10 or higher don't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 10) { + aslOptions = 0; + } +#endif // TARGET_OS_SIMULATOR + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // asl is deprecated + // Initialize the ASL client handle. + sGULLoggerClient = asl_open(NULL, kGULLoggerASLClientFacilityName, aslOptions); + sGULLoggerMaximumLevel = GULLoggerLevelNotice; + + // Set the filter used by system/device log. Initialize in default mode. + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE)); + + sGULClientQueue = dispatch_queue_create("GULLoggingClientQueue", DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(sGULClientQueue, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); +#ifdef DEBUG + sMessageCodeRegex = [NSRegularExpression regularExpressionWithPattern:kMessageCodePattern + options:0 + error:NULL]; +#endif + }); +} + +void GULLoggerEnableSTDERR(void) { + asl_add_log_file(sGULLoggerClient, STDERR_FILENO); +} + +void GULLoggerForceDebug(void) { + // We should enable debug mode if we're not running from App Store. + if (![GULAppEnvironmentUtil isFromAppStore]) { + sGULLoggerDebugMode = YES; + GULSetLoggerLevel(GULLoggerLevelDebug); + } +} + +__attribute__((no_sanitize("thread"))) void GULSetLoggerLevel(GULLoggerLevel loggerLevel) { + if (loggerLevel < GULLoggerLevelMin || loggerLevel > GULLoggerLevelMax) { + GULLogError(kGULLoggerLogger, NO, @"I-COR000023", @"Invalid logger level, %ld", + (long)loggerLevel); + return; + } + GULLoggerInitializeASL(); + // We should not raise the logger level if we are running from App Store. + if (loggerLevel >= GULLoggerLevelNotice && [GULAppEnvironmentUtil isFromAppStore]) { + return; + } + + sGULLoggerMaximumLevel = loggerLevel; + dispatch_async(sGULClientQueue, ^{ + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(loggerLevel)); + }); +} + +/** + * Check if the level is high enough to be loggable. + */ +__attribute__((no_sanitize("thread"))) BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel) { + GULLoggerInitializeASL(); + if (sGULLoggerDebugMode) { + return YES; + } + return (BOOL)(loggerLevel <= sGULLoggerMaximumLevel); +} + +#ifdef DEBUG +void GULResetLogger() { + sGULLoggerOnceToken = 0; +} + +aslclient getGULLoggerClient() { + return sGULLoggerClient; +} + +dispatch_queue_t getGULClientQueue() { + return sGULClientQueue; +} + +BOOL getGULLoggerDebugMode() { + return sGULLoggerDebugMode; +} +#endif + +void GULLoggerRegisterVersion(const char *version) { + sVersion = version; +} + +void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + GULLoggerInitializeASL(); + if (!(level <= sGULLoggerMaximumLevel || sGULLoggerDebugMode || forceLog)) { + return; + } + +#ifdef DEBUG + NSCAssert(messageCode.length == 11, @"Incorrect message code length."); + NSRange messageCodeRange = NSMakeRange(0, messageCode.length); + NSUInteger numberOfMatches = [sMessageCodeRegex numberOfMatchesInString:messageCode + options:0 + range:messageCodeRange]; + NSCAssert(numberOfMatches == 1, @"Incorrect message code format."); +#endif + NSString *logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr]; + logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg]; + dispatch_async(sGULClientQueue, ^{ + asl_log(sGULLoggerClient, NULL, level, "%s", logMsg.UTF8String); + }); +} +#pragma clang diagnostic pop + +/** + * Generates the logging functions using macros. + * + * Calling GULLogError(kGULLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-COR000001] Configure blah failed. + * Calling GULLogDebug(kGULLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-COR000001] Configure succeed. + */ +#define GUL_LOGGING_FUNCTION(level) \ + void GULLog##level(GULLoggerService service, BOOL force, NSString *messageCode, \ + NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + GULLogBasic(GULLoggerLevel##level, service, force, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +GUL_LOGGING_FUNCTION(Error) +GUL_LOGGING_FUNCTION(Warning) +GUL_LOGGING_FUNCTION(Notice) +GUL_LOGGING_FUNCTION(Info) +GUL_LOGGING_FUNCTION(Debug) + +#undef GUL_MAKE_LOGGER + +#pragma mark - GULLoggerWrapper + +@implementation GULLoggerWrapper + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + GULLogBasic(level, service, NO, messageCode, message, args); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h new file mode 100644 index 0000000..ff42576 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The services used in the logger. + */ +typedef NSString *const GULLoggerService; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initialize GULLogger. + */ +extern void GULLoggerInitializeASL(void); + +/** + * Override log level to Debug. + */ +void GULLoggerForceDebug(void); + +/** + * Turn on logging to STDERR. + */ +extern void GULLoggerEnableSTDERR(void); + +/** + * Changes the default logging level of GULLoggerLevelNotice to a user-specified level. + * The default level cannot be set above GULLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern void GULSetLoggerLevel(GULLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel); + +/** + * Register version to include in logs. + * (required) version + */ +extern void GULLoggerRegisterVersion(const char *version); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type GULLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * GULLogError(kGULLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void GULLogError(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogWarning(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogNotice(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogInfo(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogDebug(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface GULLoggerWrapper : NSObject + +/** + * Objective-C wrapper for GULLogBasic to allow weak linking to GULLogger + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h new file mode 100644 index 0000000..81ff212 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, GULLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + GULLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + GULLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + GULLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + GULLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + GULLoggerLevelDebug = 7, + /** Minimum log level. */ + GULLoggerLevelMin = GULLoggerLevelError, + /** Maximum log level. */ + GULLoggerLevelMax = GULLoggerLevelDebug +} NS_SWIFT_NAME(GoogleLoggerLevel); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m new file mode 100644 index 0000000..e58df96 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m @@ -0,0 +1,185 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULSwizzler.h" + +#import + +#import +#import "../Common/GULLoggerCodes.h" + +#ifdef GUL_UNSWIZZLING_ENABLED +#import +// We need a private method for an assert. +#import +#endif + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilites/MethodSwizzler]"; + +dispatch_queue_t GetGULSwizzlingQueue() { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.GULSwizzler", DISPATCH_QUEUE_SERIAL); + }); + return queue; +} + +@implementation GULSwizzler + ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block { + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + Class resolvedClass = aClass; + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + resolvedClass = object_getClass(aClass); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"You're attempting to swizzle a method that doesn't exist. (%@, %@)", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + IMP newImp = imp_implementationWithBlock(block); + +#ifdef GUL_UNSWIZZLING_ENABLED + IMP currentImp = class_getMethodImplementation(resolvedClass, selector); + [[GULSwizzlingCache sharedInstance] cacheCurrentIMP:currentImp + forNewIMP:newImp + forClass:resolvedClass + withSelector:selector]; +#endif + + const char *typeEncoding = method_getTypeEncoding(method); + __unused IMP originalImpOfClass = + class_replaceMethod(resolvedClass, selector, newImp, typeEncoding); + +#ifdef GUL_UNSWIZZLING_ENABLED + // If !originalImpOfClass, then the IMP came from a superclass. + if (originalImpOfClass) { + if (originalImpOfClass != + [[GULSwizzlingCache sharedInstance] originalIMPOfCurrentIMP:currentImp]) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeMethodSwizzling000], + @"Swizzling class: %@ SEL:%@ after it has been previously been swizzled.", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + } + } +#endif + }); +} + ++ (void)unswizzleClass:(Class)aClass selector:(SEL)selector isClassSelector:(BOOL)isClassSelector { +#ifdef GUL_UNSWIZZLING_ENABLED + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(aClass != nil && selector != nil, @"You cannot unswizzle a nil class or selector."); + Method method = nil; + Class resolvedClass = aClass; + if (isClassSelector) { + resolvedClass = object_getClass(aClass); + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"Couldn't find the method you're unswizzling in the runtime."); + IMP originalImp = [[GULSwizzlingCache sharedInstance] cachedIMPForClass:resolvedClass + withSelector:selector]; + NSAssert(originalImp, @"This class/selector combination hasn't been swizzled"); + IMP currentImp = method_setImplementation(method, originalImp); + BOOL didRemoveBlock = imp_removeBlock(currentImp); + NSAssert(didRemoveBlock, @"Wasn't able to remove the block of a swizzled IMP."); + [[GULSwizzlingCache sharedInstance] clearCacheForSwizzledIMP:currentImp + selector:selector + aClass:resolvedClass]; + }); +#else + NSAssert(NO, @"Unswizzling is disabled."); +#endif +} + ++ (nullable IMP)originalImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { +#ifdef GUL_UNSWIZZLING_ENABLED + __block IMP originalImp = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Class resolvedClass = isClassSelector ? object_getClass(aClass) : aClass; + originalImp = [[GULSwizzlingCache sharedInstance] cachedIMPForClass:resolvedClass + withSelector:selector]; + NSAssert(originalImp, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + }); + return originalImp; +#else + NSAssert(NO, @"Unswizzling is disabled and the original IMP is not cached."); + return nil; +#endif +} + ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + if (selector == NULL || aClass == nil) { + return nil; + } + __block IMP currentIMP = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"The Method for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + if (method == nil) { + return; + } + currentIMP = method_getImplementation(method); + NSAssert(currentIMP, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + }); + return currentIMP; +} + ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector { + Method method = isClassSelector ? class_getClassMethod(aClass, selector) + : class_getInstanceMethod(aClass, selector); + return method != nil; +} + ++ (NSArray *)ivarObjectsForObject:(id)object { + NSMutableArray *array = [NSMutableArray array]; + unsigned int count; + Ivar *vars = class_copyIvarList([object class], &count); + for (NSUInteger i = 0; i < count; i++) { + const char *typeEncoding = ivar_getTypeEncoding(vars[i]); + // Check to see if the ivar is an object. + if (strncmp(typeEncoding, "@", 1) == 0) { + id ivarObject = object_getIvar(object, vars[i]); + [array addObject:ivarObject]; + } + } + free(vars); + return array; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h new file mode 100644 index 0000000..a33262a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h @@ -0,0 +1,207 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * GULOriginalIMPConvenienceMacros.h + * + * This header contains convenience macros for invoking the original IMP of a swizzled method. + */ + +/** + * Invokes original IMP when the original selector takes no arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + */ +#define GUL_INVOKE_ORIGINAL_IMP0(__receivingObject, __swizzledSEL, __returnType, __originalIMP) \ + ((__returnType(*)(id, SEL))__originalIMP)(__receivingObject, __swizzledSEL) + +/** + * Invokes original IMP when the original selector takes 1 argument. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP1(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1)))__originalIMP)(__receivingObject, __swizzledSEL, \ + __arg1) + +/** + * Invokes original IMP when the original selector takes 2 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP2(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2) + +/** + * Invokes original IMP when the original selector takes 3 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP3(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), \ + __typeof__(__arg3)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3) + +/** + * Invokes original IMP when the original selector takes 4 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP4(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3, __arg4) + +/** + * Invokes original IMP when the original selector takes 5 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP5(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5) + +/** + * Invokes original IMP when the original selector takes 6 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP6(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) + +/** + * Invokes original IMP when the original selector takes 7 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP7(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) + +/** + * Invokes original IMP when the original selector takes 8 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP8(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8) + +/** + * Invokes original IMP when the original selector takes 9 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + * @param __arg9 The ninth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP9(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8, \ + __arg9) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8), __typeof__(__arg9)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8, __arg9) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h new file mode 100644 index 0000000..ab008ca --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class handles the runtime manipulation necessary to instrument selectors. It stores the + * classes and selectors that have been swizzled, and runs all operations on its own queue. + */ +@interface GULSwizzler : NSObject + +/** Manipulates the Objective-C runtime to replace the original IMP with the supplied block. + * + * @param aClass The class to swizzle. + * @param selector The selector of the class to swizzle. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @param block The block that replaces the original IMP. + */ ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block; + +/** Restores the original implementation. + * + * @param aClass The class to unswizzle. + * @param selector The selector to restore the original implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + */ ++ (void)unswizzleClass:(Class)aClass selector:(SEL)selector isClassSelector:(BOOL)isClassSelector; + +/** Returns the current IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime. + */ ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Returns the original IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime before any consumer or GULSwizzler + * swizzled. + */ ++ (nullable IMP)originalImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Checks the runtime to see if a selector exists on a class. If a property is declared as + * @dynamic, we have a reverse swizzling situation, where the implementation of a method exists + * only in concrete subclasses, and NOT in the superclass. We can detect that situation using + * this helper method. Similarly, we can detect situations where a class doesn't implement a + * protocol method. + * + * @param selector The selector to check for. + * @param aClass The class to check. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return YES if the method was found in this selector/class combination, NO otherwise. + */ ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector; + +/** Returns a list of all Objective-C (and not primitive) ivars contained by the given object. + * + * @param object The object whose ivars will be iterated. + * @return The list of ivar objects. + */ ++ (NSArray *)ivarObjectsForObject:(id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h new file mode 100644 index 0000000..36f94a7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h @@ -0,0 +1,49 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework. + +// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given +// such data. To handle data of that size you really should be streaming it rather then doing it all +// in memory. + +@interface NSData (GULGzip) + +/// Returns an data as the result of decompressing the payload of |data|.The data to decompress must +/// be a gzipped payloads. ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error; + +/// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default +/// compression level. ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error; + +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain; +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber +FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber + +typedef NS_ENUM(NSInteger, GULNSDataZlibError) { + GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024, + // An internal zlib error. + // GULNSDataZlibErrorKey will contain the error value. + // NSLocalizedDescriptionKey may contain an error string from zlib. + // Look in zlib.h for list of errors. + GULNSDataZlibErrorInternal, + // There was left over data in the buffer that was not used. + // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes. + GULNSDataZlibErrorDataRemaining +}; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m new file mode 100644 index 0000000..cd3394a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m @@ -0,0 +1,207 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GULNSData+zlib.h" + +#import + +#define kChunkSize 1024 +#define Z_DEFAULT_COMPRESSION (-1) + +NSString *const GULNSDataZlibErrorDomain = @"com.google.GULNSDataZlibErrorDomain"; +NSString *const GULNSDataZlibErrorKey = @"GULNSDataZlibErrorKey"; +NSString *const GULNSDataZlibRemainingBytesKey = @"GULNSDataZlibRemainingBytesKey"; + +@implementation NSData (GULGzip) + ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + int windowBits = 15; // 15 to enable any window size + windowBits += 32; // and +32 to enable zlib or gzip header detection. + + int retCode; + if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 4x the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length * 4)]; + unsigned char output[kChunkSize]; + + // Loop to collect the data. + do { + // Update what we're passing in. + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = inflate(&strm, Z_NO_FLUSH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + if (strm.msg) { + NSString *message = [NSString stringWithUTF8String:strm.msg]; + if (message) { + [userInfo setObject:message forKey:NSLocalizedDescriptionKey]; + } + } + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + inflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // Make sure there wasn't more data tacked onto the end of a valid compressed stream. + if (strm.avail_in != 0) { + if (error) { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in] + forKey:GULNSDataZlibRemainingBytesKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorDataRemaining + userInfo:userInfo]; + } + result = nil; + } + // The only way out of the loop was by hitting the end of the stream. + NSAssert(retCode == Z_STREAM_END, + @"Thought we finished inflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + inflateEnd(&strm); + + return result; +} + ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + if (error) { + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorGreaterThan32BitsToCompress + userInfo:nil]; + } + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m new file mode 100644 index 0000000..d281eb4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m @@ -0,0 +1,97 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULMutableDictionary.h" + +@implementation GULMutableDictionary { + /// The mutable dictionary. + NSMutableDictionary *_objects; + + /// Serial synchronization queue. All reads should use dispatch_sync, while writes use + /// dispatch_async. + dispatch_queue_t _queue; +} + +- (instancetype)init { + self = [super init]; + + if (self) { + _objects = [[NSMutableDictionary alloc] init]; + _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (NSString *)description { + __block NSString *description; + dispatch_sync(_queue, ^{ + description = self->_objects.description; + }); + return description; +} + +- (id)objectForKey:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = self->_objects[key]; + }); + return object; +} + +- (void)setObject:(id)object forKey:(id)key { + dispatch_async(_queue, ^{ + self->_objects[key] = object; + }); +} + +- (void)removeObjectForKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_async(_queue, ^{ + [self->_objects removeAllObjects]; + }); +} + +- (NSUInteger)count { + __block NSUInteger count; + dispatch_sync(_queue, ^{ + count = self->_objects.count; + }); + return count; +} + +- (id)objectForKeyedSubscript:(id)key { + // The method this calls is already synchronized. + return [self objectForKey:key]; +} + +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + // The method this calls is already synchronized. + [self setObject:obj forKey:key]; +} + +- (NSDictionary *)dictionary { + __block NSDictionary *dictionary; + dispatch_sync(_queue, ^{ + dictionary = [self->_objects copy]; + }); + return dictionary; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m new file mode 100644 index 0000000..c322727 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m @@ -0,0 +1,389 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULNetwork.h" +#import "Private/GULNetworkMessageCode.h" + +#import +#import +#import +#import "Private/GULMutableDictionary.h" +#import "Private/GULNetworkConstants.h" + +/// Constant string for request header Content-Encoding. +static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; + +/// Constant string for request header Content-Encoding value. +static NSString *const kGULNetworkContentCompressionValue = @"gzip"; + +/// Constant string for request header Content-Length. +static NSString *const kGULNetworkContentLengthKey = @"Content-Length"; + +/// Constant string for request header Content-Type. +static NSString *const kGULNetworkContentTypeKey = @"Content-Type"; + +/// Constant string for request header Content-Type value. +static NSString *const kGULNetworkContentTypeValue = @"application/x-www-form-urlencoded"; + +/// Constant string for GET request method. +static NSString *const kGULNetworkGETRequestMethod = @"GET"; + +/// Constant string for POST request method. +static NSString *const kGULNetworkPOSTRequestMethod = @"POST"; + +/// Default constant string as a prefix for network logger. +static NSString *const kGULNetworkLogTag = @"Google/Utilities/Network"; + +@interface GULNetwork () +@end + +@implementation GULNetwork { + /// Network reachability. + GULReachabilityChecker *_reachability; + + /// The dictionary of requests by session IDs { NSString : id }. + GULMutableDictionary *_requests; +} + +- (instancetype)init { + return [self initWithReachabilityHost:kGULNetworkReachabilityHost]; +} + +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { + self = [super init]; + if (self) { + // Setup reachability. + _reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:reachabilityHost]; + if (![_reachability start]) { + return nil; + } + + _requests = [[GULMutableDictionary alloc] init]; + _timeoutInterval = kGULNetworkTimeOutInterval; + } + return self; +} + +- (void)dealloc { + _reachability.reachabilityDelegate = nil; + [_reachability stop]; +} + +#pragma mark - External Methods + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler { + [GULNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID + completionHandler:completionHandler]; +} + +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + NSError *compressError = nil; + NSData *compressedData = [NSData gul_dataByGzippingData:payload error:&compressError]; + if (!compressedData || compressError) { + if (compressError || payload.length > 0) { + // If the payload is not empty but it fails to compress the payload, something has been wrong. + [self handleErrorWithCode:GULErrorCodeNetworkPayloadCompression + queue:queue + withHandler:handler]; + return nil; + } + compressedData = [[NSData alloc] init]; + } + + NSString *postLength = @(compressedData.length).stringValue; + + // Set up the request with the compressed data. + [request setValue:postLength forHTTPHeaderField:kGULNetworkContentLengthKey]; + request.HTTPBody = compressedData; + request.HTTPMethod = kGULNetworkPOSTRequestMethod; + [request setValue:kGULNetworkContentTypeValue forHTTPHeaderField:kGULNetworkContentTypeKey]; + [request setValue:kGULNetworkContentCompressionValue + forHTTPHeaderField:kGULNetworkContentCompressionKey]; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncPOSTRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, + NSString *sessionID, NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork000 + message:@"Uploading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + request.HTTPMethod = kGULNetworkGETRequestMethod; + request.allHTTPHeaderFields = headers; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncGETRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, + NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork001 + message:@"Downloading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (BOOL)hasUploadInProgress { + return _requests.count > 0; +} + +#pragma mark - Network Reachability + +/// Tells reachability delegate to call reachabilityDidChangeToStatus: to notify the network +/// reachability has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + _networkConnected = (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); + [_reachabilityDelegate reachabilityDidChange]; +} + +#pragma mark - Network logger delegate + +- (void)setLoggerDelegate:(id)loggerDelegate { + // Explicitly check whether the delegate responds to the methods because conformsToProtocol does + // not work correctly even though the delegate does respond to the methods. + if (!loggerDelegate || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:contexts:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:context:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:)]) { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork002], + @"Cannot set the network logger delegate: delegate does not conform to the network " + "logger protocol."); + return; + } + _loggerDelegate = loggerDelegate; +} + +#pragma mark - Private methods + +/// Handles network error and calls completion handler with the error. +- (void)handleErrorWithCode:(NSInteger)code + queue:(dispatch_queue_t)queue + withHandler:(GULNetworkCompletionHandler)handler { + NSDictionary *userInfo = @{kGULNetworkErrorContext : @"Failed to create network request"}; + NSError *error = [[NSError alloc] initWithDomain:kGULNetworkErrorDomain + code:code + userInfo:userInfo]; + [self GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeNetwork002 + message:@"Failed to create network request. Code, error" + contexts:@[ @(code), error ]]; + if (handler) { + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + handler(nil, nil, error); + }); + } +} + +#pragma mark - Network logger + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts { + // Let the delegate log the message if there is a valid logger delegate. Otherwise, just log + // errors/warnings/info messages to the console log. + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + contexts:contexts]; + return; + } + if (_isDebugModeEnabled || logLevel == kGULNetworkLogLevelError || + logLevel == kGULNetworkLogLevelWarning || logLevel == kGULNetworkLogLevelInfo) { + NSString *formattedMessage = GULStringWithLogMessage(message, logLevel, contexts); + NSLog(@"%@", formattedMessage); + GULLogBasic((GULLoggerLevel)logLevel, kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, + NULL); + } +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + context:context]; + return; + } + NSArray *contexts = context ? @[ context ] : @[]; + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; + return; + } + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; +} + +/// Returns a string for the given log level (e.g. kGULNetworkLogLevelError -> @"ERROR"). +static NSString *GULLogLevelDescriptionFromLogLevel(GULNetworkLogLevel logLevel) { + static NSDictionary *levelNames = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + levelNames = @{ + @(kGULNetworkLogLevelError) : @"ERROR", + @(kGULNetworkLogLevelWarning) : @"WARNING", + @(kGULNetworkLogLevelInfo) : @"INFO", + @(kGULNetworkLogLevelDebug) : @"DEBUG" + }; + }); + return levelNames[@(logLevel)]; +} + +/// Returns a formatted string to be used for console logging. +static NSString *GULStringWithLogMessage(NSString *message, + GULNetworkLogLevel logLevel, + NSArray *contexts) { + if (!message) { + message = @"(Message was nil)"; + } else if (!message.length) { + message = @"(Message was empty)"; + } + NSMutableString *result = [[NSMutableString alloc] + initWithFormat:@"<%@/%@> %@", kGULNetworkLogTag, GULLogLevelDescriptionFromLogLevel(logLevel), + message]; + + if (!contexts.count) { + return result; + } + + NSMutableArray *formattedContexts = [[NSMutableArray alloc] init]; + for (id item in contexts) { + [formattedContexts addObject:(item != [NSNull null] ? item : @"(nil)")]; + } + + [result appendString:@": "]; + [result appendString:[formattedContexts componentsJoinedByString:@", "]]; + return result; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m new file mode 100644 index 0000000..90bd03d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m @@ -0,0 +1,40 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULNetworkConstants.h" + +#import + +NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload"; +NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network"; +NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory"; +const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour +const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute. +NSString *const kGULNetworkReachabilityHost = @"app-measurement.com"; +NSString *const kGULNetworkErrorContext = @"Context"; + +const int kGULNetworkHTTPStatusOK = 200; +const int kGULNetworkHTTPStatusNoContent = 204; +const int kGULNetworkHTTPStatusCodeMultipleChoices = 300; +const int kGULNetworkHTTPStatusCodeMovedPermanently = 301; +const int kGULNetworkHTTPStatusCodeFound = 302; +const int kGULNetworkHTTPStatusCodeNotModified = 304; +const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307; +const int kGULNetworkHTTPStatusCodeNotFound = 404; +const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429; +const int kGULNetworkHTTPStatusCodeUnavailable = 503; + +NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain"; + +GULLoggerService kGULLoggerNetwork = @"[GULNetwork]"; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m new file mode 100644 index 0000000..416a736 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m @@ -0,0 +1,740 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "Private/GULNetworkURLSession.h" + +#import +#import "Private/GULMutableDictionary.h" +#import "Private/GULNetworkConstants.h" +#import "Private/GULNetworkMessageCode.h" + +@interface GULNetworkURLSession () +@end + +@implementation GULNetworkURLSession { + /// The handler to be called when the request completes or error has occurs. + GULNetworkURLSessionCompletionHandler _completionHandler; + + /// Session ID generated randomly with a fixed prefix. + NSString *_sessionID; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + /// The session configuration. NSURLSessionConfiguration' is only available on iOS 7.0 or newer. + NSURLSessionConfiguration *_sessionConfig; + + /// The current NSURLSession. + NSURLSession *__weak _Nullable _URLSession; +#pragma clang diagnostic pop + + /// The path to the directory where all temporary files are stored before uploading. + NSURL *_networkDirectoryURL; + + /// The downloaded data from fetching. + NSData *_downloadedData; + + /// The path to the temporary file which stores the uploading data. + NSURL *_uploadingFileURL; + + /// The current request. + NSURLRequest *_request; +} + +#pragma mark - Init + +- (instancetype)initWithNetworkLoggerDelegate:(id)networkLoggerDelegate { + self = [super init]; + if (self) { + // Create URL to the directory where all temporary files to upload have to be stored. + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *applicationSupportDirectory = paths.firstObject; + NSArray *tempPathComponents = @[ + applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory, + kGULNetworkTempDirectoryName + ]; + _networkDirectoryURL = [NSURL fileURLWithPathComponents:tempPathComponents]; + _sessionID = [NSString stringWithFormat:@"%@-%@", kGULNetworkBackgroundSessionConfigIDPrefix, + [[NSUUID UUID] UUIDString]]; + _loggerDelegate = networkLoggerDelegate; + } + return self; +} + +#pragma mark - External Methods + +#pragma mark - To be called from AppDelegate + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler: + (GULNetworkSystemCompletionHandler)systemCompletionHandler { + // The session may not be Analytics background. Ignore those that do not have the prefix. + if (![sessionID hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + return; + } + GULNetworkURLSession *fetcher = [self fetcherWithSessionIdentifier:sessionID]; + if (fetcher != nil) { + [fetcher addSystemCompletionHandler:systemCompletionHandler forSession:sessionID]; + } else { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork003], + @"Failed to retrieve background session with ID %@ after app is relaunched.", + sessionID); + } +} + +#pragma mark - External Methods + +/// Sends an async POST request using NSURLSession for iOS >= 7.0, and returns an ID of the +/// connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + // NSURLSessionUploadTask does not work with NSData in the background. + // To avoid this issue, write the data to a temporary file to upload it. + // Make a temporary file with the data subset. + _uploadingFileURL = [self temporaryFilePathWithSessionID:_sessionID]; + NSError *writeError; + NSURLSessionUploadTask *postRequestTask; + NSURLSession *session; + BOOL didWriteFile = NO; + + // Clean up the entire temp folder to avoid temp files that remain in case the previous session + // crashed and did not clean up. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // If there is no background network enabled, no need to write to file. This will allow default + // network session which runs on the foreground. + if (_backgroundNetworkEnabled && [self ensureTemporaryDirectoryExists]) { + didWriteFile = [request.HTTPBody writeToFile:_uploadingFileURL.path + options:NSDataWritingAtomic + error:&writeError]; + + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession000 + message:@"Failed to write request data to file" + context:writeError]; + } + } + + if (didWriteFile) { + // Exclude this file from backing up to iTunes. There are conflicting reports that excluding + // directory from backing up does not exclude files of that directory from backing up. + [self excludeFromBackupForURL:_uploadingFileURL]; + + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromFile:_uploadingFileURL]; + } else { + // If we cannot write to file, just send it in the foreground. + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromData:request.HTTPBody]; + } + + if (!session || !postRequestTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + // Store completion handler because background session does not accept handler block but custom + // delegate. + _completionHandler = [handler copy]; + [postRequestTask resume]; + + return _sessionID; +} + +/// Sends an async GET request using NSURLSession for iOS >= 7.0, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + if (_backgroundNetworkEnabled) { + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + } else { + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + } + + [self populateSessionConfig:_sessionConfig withRequest:request]; + + // Do not cache the GET request. + _sessionConfig.URLCache = nil; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; + + if (!session || !downloadTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + _completionHandler = [handler copy]; + [downloadTask resume]; + + return _sessionID; +} + +#pragma mark - NSURLSessionTaskDelegate + +/// Called by the NSURLSession once the download task is completed. The file is saved in the +/// provided URL so we need to read the data and store into _downloadedData. Once the session is +/// completed, URLSession:task:didCompleteWithError will be called and the completion handler will +/// be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:(NSURL *)url API_AVAILABLE(ios(7.0)) { + if (!url.path) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession001 + message:@"Unable to read downloaded data from empty temp path"]; + _downloadedData = nil; + return; + } + + NSError *error; + _downloadedData = [NSData dataWithContentsOfFile:url.path options:0 error:&error]; + + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession002 + message:@"Cannot read the content of downloaded data" + context:error]; + _downloadedData = nil; + } +} + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session + API_AVAILABLE(ios(7.0)) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession003 + message:@"Background session finished" + context:session.configuration.identifier]; + [self callSystemCompletionHandler:session.configuration.identifier]; +} +#endif + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error API_AVAILABLE(ios(7.0)) { + // Avoid any chance of recursive behavior leading to it being used repeatedly. + GULNetworkURLSessionCompletionHandler handler = _completionHandler; + _completionHandler = nil; + + if (task.response) { + // The following assertion should always be true for HTTP requests, see https://goo.gl/gVLxT7. + NSAssert([task.response isKindOfClass:[NSHTTPURLResponse class]], @"URL response must be HTTP"); + + // The server responded so ignore the error created by the system. + error = nil; + } else if (!error) { + error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkInvalidResponse + userInfo:@{kGULNetworkErrorContext : @"Network Error: Empty network response"}]; + } + + [self callCompletionHandler:handler + withResponse:(NSHTTPURLResponse *)task.response + data:_downloadedData + error:error]; + + // Remove the temp file to avoid trashing devices with lots of temp files. + [self removeTempItemAtURL:_uploadingFileURL]; + + // Try to clean up stale files again. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // This is called without checking the sessionID here since non-background sessions + // won't have an ID. + [session finishTasksAndInvalidate]; + + // Explicitly remove the session so it won't be reused. The weak map table should + // remove the session on deallocation, but dealloc may not happen immediately after + // calling `finishTasksAndInvalidate`. + NSString *sessionID = session.configuration.identifier; + [[self class] setSessionInFetcherMap:nil forSessionID:sessionID]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential *credential))completionHandler + API_AVAILABLE(ios(7.0)) { + // The handling is modeled after GTMSessionFetcher. + if ([challenge.protectionSpace.authenticationMethod + isEqualToString:NSURLAuthenticationMethodServerTrust]) { + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession004 + message:@"Received empty server trust for host. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + return; + } + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + if (!credential) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession005 + message:@"Unable to verify server identity. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + return; + } + + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession006 + message:@"Received SSL challenge for host. Host" + context:_request.URL]; + + void (^callback)(BOOL) = ^(BOOL allow) { + if (allow) { + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + [self->_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession007 + message:@"Cancelling authentication challenge for host. Host" + context:self->_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_async(evaluateBackgroundQueue, ^{ + SecTrustResultType trustEval = kSecTrustResultInvalid; + BOOL shouldAllow; + OSStatus trustError; + + @synchronized([GULNetworkURLSession class]) { + trustError = SecTrustEvaluate(serverTrust, &trustEval); + } + + if (trustError != errSecSuccess) { + [self->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession008 + message:@"Cannot evaluate server trust. Error, host" + contexts:@[ @(trustError), self->_request.URL ]]; + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + shouldAllow = + (trustEval == kSecTrustResultUnspecified || trustEval == kSecTrustResultProceed); + } + + // Call the call back with the permission. + callback(shouldAllow); + + CFRelease(serverTrust); + }); + return; + } + + // Default handling for other Auth Challenges. + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} + +#pragma mark - Internal Methods + +/// Stores system completion handler with session ID as key. +- (void)addSystemCompletionHandler:(GULNetworkSystemCompletionHandler)handler + forSession:(NSString *)identifier { + if (!handler) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession009 + message:@"Cannot store nil system completion handler in network"]; + return; + } + + if (!identifier.length) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession010 + message:@"Cannot store system completion handler with empty network " + "session identifier"]; + return; + } + + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + if (systemCompletionHandlers[identifier]) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession011 + message:@"Got multiple system handlers for a single session ID" + context:identifier]; + } + + systemCompletionHandlers[identifier] = handler; +} + +/// Calls the system provided completion handler with the session ID stored in the dictionary. +/// The handler will be removed from the dictionary after being called. +- (void)callSystemCompletionHandler:(NSString *)identifier { + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + GULNetworkSystemCompletionHandler handler = [systemCompletionHandlers objectForKey:identifier]; + + if (handler) { + [systemCompletionHandlers removeObjectForKey:identifier]; + + dispatch_async(dispatch_get_main_queue(), ^{ + handler(); + }); + } +} + +/// Sets or updates the session ID of this session. +- (void)setSessionID:(NSString *)sessionID { + _sessionID = [sessionID copy]; +} + +/// Creates a background session configuration with the session ID using the supported method. +- (NSURLSessionConfiguration *)backgroundSessionConfigWithSessionID:(NSString *)sessionID + API_AVAILABLE(ios(7.0)) { +#if (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10) || \ + TARGET_OS_TV || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) + + // iOS 8/10.10 builds require the new backgroundSessionConfiguration method name. + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; + +#elif (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0) + + // Do a runtime check to avoid a deprecation warning about using + // +backgroundSessionConfiguration: on iOS 8. + if ([NSURLSessionConfiguration + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + // Running on iOS 8+/OS X 10.10+. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; +#pragma clang diagnostic pop + } else { + // Running on iOS 7/OS X 10.9. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; + } + +#else + // Building with an SDK earlier than iOS 8/OS X 10.10. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; +#endif +} + +- (void)maybeRemoveTempFilesAtURL:(NSURL *)folderURL expiringTime:(NSTimeInterval)staleTime { + if (!folderURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + NSArray *properties = @[ NSURLCreationDateKey ]; + NSArray *directoryContent = + [fileManager contentsOfDirectoryAtURL:folderURL + includingPropertiesForKeys:properties + options:NSDirectoryEnumerationSkipsSubdirectoryDescendants + error:&error]; + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession012 + message:@"Cannot get files from the temporary network folder. Error" + context:error]; + return; + } + + if (!directoryContent.count) { + return; + } + + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + for (NSURL *tempFile in directoryContent) { + NSDate *creationDate; + BOOL getCreationDate = [tempFile getResourceValue:&creationDate + forKey:NSURLCreationDateKey + error:NULL]; + if (!getCreationDate) { + continue; + } + NSTimeInterval creationTimeInterval = creationDate.timeIntervalSince1970; + if (fabs(now - creationTimeInterval) > staleTime) { + [self removeTempItemAtURL:tempFile]; + } + } +} + +/// Removes the temporary file written to disk for sending the request. It has to be cleaned up +/// after the session is done. +- (void)removeTempItemAtURL:(NSURL *)fileURL { + if (!fileURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + if (![fileManager removeItemAtURL:fileURL error:&error] && error.code != NSFileNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession013 + message:@"Failed to remove temporary uploading data file. Error" + context:error.localizedDescription]; + } +} + +/// Gets the fetcher with the session ID. ++ (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GULNetworkURLSession *session = [self sessionFromFetcherMapForSessionID:sessionIdentifier]; + if (!session && [sessionIdentifier hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + session = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:nil]; + [session setSessionID:sessionIdentifier]; + [self setSessionInFetcherMap:session forSessionID:sessionIdentifier]; + } + return session; +} + +/// Returns a map of the fetcher by session ID. Creates a map if it is not created. +/// When reading and writing from/to the session map, don't use this method directly. +/// To avoid thread safety issues, use one of the helper methods at the bottom of the +/// file: setSessionInFetcherMap:forSessionID:, sessionFromFetcherMapForSessionID: ++ (NSMapTable *)sessionIDToFetcherMap { + static NSMapTable *sessionIDToFetcherMap; + + static dispatch_once_t sessionMapOnceToken; + dispatch_once(&sessionMapOnceToken, ^{ + sessionIDToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return sessionIDToFetcherMap; +} + ++ (NSLock *)sessionIDToFetcherMapReadWriteLock { + static NSLock *lock; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + return lock; +} + +/// Returns a map of system provided completion handler by session ID. Creates a map if it is not +/// created. ++ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary { + static GULMutableDictionary *systemCompletionHandlers; + + static dispatch_once_t systemCompletionHandlerOnceToken; + dispatch_once(&systemCompletionHandlerOnceToken, ^{ + systemCompletionHandlers = [[GULMutableDictionary alloc] init]; + }); + return systemCompletionHandlers; +} + +- (NSURL *)temporaryFilePathWithSessionID:(NSString *)sessionID { + NSString *tempName = [NSString stringWithFormat:@"GULUpload_temp_%@", sessionID]; + return [_networkDirectoryURL URLByAppendingPathComponent:tempName]; +} + +/// Makes sure that the directory to store temp files exists. If not, tries to create it and returns +/// YES. If there is anything wrong, returns NO. +- (BOOL)ensureTemporaryDirectoryExists { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + // Create a temporary directory if it does not exist or was deleted. + if ([_networkDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + return YES; + } + + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession014 + message:@"Error while trying to access Network temp folder. Error" + context:error]; + } + + NSError *writeError = nil; + + [fileManager createDirectoryAtURL:_networkDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&writeError]; + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession015 + message:@"Cannot create temporary directory. Error" + context:writeError]; + return NO; + } + + // Set the iCloud exclusion attribute on the Documents URL. + [self excludeFromBackupForURL:_networkDirectoryURL]; + + return YES; +} + +- (void)excludeFromBackupForURL:(NSURL *)url { + if (!url.path) { + return; + } + + // Set the iCloud exclusion attribute on the Documents URL. + NSError *preventBackupError = nil; + [url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&preventBackupError]; + if (preventBackupError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession016 + message:@"Cannot exclude temporary folder from iTunes backup"]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler API_AVAILABLE(ios(7.0)) { + NSArray *nonAllowedRedirectionCodes = @[ + @(kGULNetworkHTTPStatusCodeFound), @(kGULNetworkHTTPStatusCodeMovedPermanently), + @(kGULNetworkHTTPStatusCodeMovedTemporarily), @(kGULNetworkHTTPStatusCodeMultipleChoices) + ]; + + // Allow those not in the non allowed list to be followed. + if (![nonAllowedRedirectionCodes containsObject:@(response.statusCode)]) { + completionHandler(request); + return; + } + + // Do not allow redirection if the response code is in the non-allowed list. + NSURLRequest *newRequest = request; + + if (response) { + newRequest = nil; + } + + completionHandler(newRequest); +} + +#pragma mark - Helper Methods + ++ (void)setSessionInFetcherMap:(GULNetworkURLSession *)session forSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *existingSession = + [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + if (existingSession) { + if (session) { + NSString *message = [NSString stringWithFormat:@"Discarding session: %@", existingSession]; + [existingSession->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelInfo + messageCode:kGULNetworkMessageCodeURLSession019 + message:message]; + } + [existingSession->_URLSession finishTasksAndInvalidate]; + } + if (session) { + [[[self class] sessionIDToFetcherMap] setObject:session forKey:sessionID]; + } else { + [[[self class] sessionIDToFetcherMap] removeObjectForKey:sessionID]; + } + [[self sessionIDToFetcherMapReadWriteLock] unlock]; +} + ++ (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *session = [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + [[self sessionIDToFetcherMapReadWriteLock] unlock]; + return session; +} + +- (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler + withResponse:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession017 + message:@"Encounter network error. Code, error" + contexts:@[ @(error.code), error ]]; + } + + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(response, data, self->_sessionID, error); + }); + } +} + +// Always use the request parameters even if the default session configuration is more restrictive. +- (void)populateSessionConfig:(NSURLSessionConfiguration *)sessionConfig + withRequest:(NSURLRequest *)request API_AVAILABLE(ios(7.0)) { + sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields; + sessionConfig.timeoutIntervalForRequest = request.timeoutInterval; + sessionConfig.timeoutIntervalForResource = request.timeoutInterval; + sessionConfig.requestCachePolicy = request.cachePolicy; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h new file mode 100644 index 0000000..a8cc45b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// A mutable dictionary that provides atomic accessor and mutators. +@interface GULMutableDictionary : NSObject + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKey:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)object forKey:(id)key; + +/// Removes the object given its session ID from the dictionary. +- (void)removeObjectForKey:(id)key; + +/// Removes all objects. +- (void)removeAllObjects; + +/// Returns the number of current objects in the dictionary. +- (NSUInteger)count; + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKeyedSubscript:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key; + +/// Returns the immutable dictionary. +- (NSDictionary *)dictionary; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h new file mode 100644 index 0000000..0e75ae5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkConstants.h" +#import "GULNetworkLoggerProtocol.h" +#import "GULNetworkURLSession.h" + +/// Delegate protocol for GULNetwork events. +@protocol GULNetworkReachabilityDelegate + +/// Tells the delegate to handle events when the network reachability changes to connected or not +/// connected. +- (void)reachabilityDidChange; + +@end + +/// The Network component that provides network status and handles network requests and responses. +/// This is not thread safe. +/// +/// NOTE: +/// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the +/// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler: +@interface GULNetwork : NSObject + +/// Indicates if network connectivity is available. +@property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected; + +/// Indicates if there are any uploads in progress. +@property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress; + +/// An optional delegate that can be used in the event when network reachability changes. +@property(nonatomic, weak) id reachabilityDelegate; + +/// An optional delegate that can be used to log messages, warnings or errors that occur in the +/// network operations. +@property(nonatomic, weak) id loggerDelegate; + +/// Indicates whether the logger should display debug messages. +@property(nonatomic, assign) BOOL isDebugModeEnabled; + +/// The time interval in seconds for the network request to timeout. +@property(nonatomic, assign) NSTimeInterval timeoutInterval; + +/// Initializes with the default reachability host. +- (instancetype)init; + +/// Initializes with a custom reachability host. +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost; + +/// Handles events when background session with the given ID has finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Compresses and sends a POST request with the provided data to the URL. The session will be +/// background session if usingBackgroundSession is YES. Otherwise, the POST session is default +/// session. Returns a session ID or nil if an error occurs. +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +/// Sends a GET request with the provided data to the URL. The session will be background session +/// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a +/// session ID or nil if an error occurs. +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h new file mode 100644 index 0000000..44d440b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Error codes in Firebase Network error domain. +/// Note: these error codes should never change. It would make it harder to decode the errors if +/// we inadvertently altered any of these codes in a future SDK version. +typedef NS_ENUM(NSInteger, GULNetworkErrorCode) { + /// Unknown error. + GULNetworkErrorCodeUnknown = 0, + /// Error occurs when the request URL is invalid. + GULErrorCodeNetworkInvalidURL = 1, + /// Error occurs when request cannot be constructed. + GULErrorCodeNetworkRequestCreation = 2, + /// Error occurs when payload cannot be compressed. + GULErrorCodeNetworkPayloadCompression = 3, + /// Error occurs when session task cannot be created. + GULErrorCodeNetworkSessionTaskCreation = 4, + /// Error occurs when there is no response. + GULErrorCodeNetworkInvalidResponse = 5 +}; + +#pragma mark - Network constants + +/// The prefix of the ID of the background session. +extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix; + +/// The sub directory to store the files of data that is being uploaded in the background. +extern NSString *const kGULNetworkApplicationSupportSubdirectory; + +/// Name of the temporary directory that stores files for background uploading. +extern NSString *const kGULNetworkTempDirectoryName; + +/// The period when the temporary uploading file can stay. +extern const NSTimeInterval kGULNetworkTempFolderExpireTime; + +/// The default network request timeout interval. +extern const NSTimeInterval kGULNetworkTimeOutInterval; + +/// The host to check the reachability of the network. +extern NSString *const kGULNetworkReachabilityHost; + +/// The key to get the error context of the UserInfo. +extern NSString *const kGULNetworkErrorContext; + +#pragma mark - Network Status Code + +extern const int kGULNetworkHTTPStatusOK; +extern const int kGULNetworkHTTPStatusNoContent; +extern const int kGULNetworkHTTPStatusCodeMultipleChoices; +extern const int kGULNetworkHTTPStatusCodeMovedPermanently; +extern const int kGULNetworkHTTPStatusCodeFound; +extern const int kGULNetworkHTTPStatusCodeNotModified; +extern const int kGULNetworkHTTPStatusCodeMovedTemporarily; +extern const int kGULNetworkHTTPStatusCodeNotFound; +extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic; +extern const int kGULNetworkHTTPStatusCodeUnavailable; + +#pragma mark - Error Domain + +extern NSString *const kGULNetworkErrorDomain; + +/// The logger service for GULNetwork. +extern GULLoggerService kGULLoggerNetwork; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h new file mode 100644 index 0000000..f1be590 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GULNetworkMessageCode.h" + +/// The log levels used by GULNetworkLogger. +typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { + kGULNetworkLogLevelError = GULLoggerLevelError, + kGULNetworkLogLevelWarning = GULLoggerLevelWarning, + kGULNetworkLogLevelInfo = GULLoggerLevelInfo, + kGULNetworkLogLevelDebug = GULLoggerLevelDebug, +}; + +@protocol GULNetworkLoggerDelegate + +@required +/// Tells the delegate to log a message with an array of contexts and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts; + +/// Tells the delegate to log a message with a context and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context; + +/// Tells the delegate to log a message with the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h new file mode 100644 index 0000000..f9d1628 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULNetworkMessageCode) { + // GULNetwork.m + kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000 + kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001 + kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002 + kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003 + // GULNetworkURLSession.m + kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000 + kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001 + kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002 + kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003 + kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004 + kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005 + kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006 + kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007 + kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008 + kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009 + kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010 + kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011 + kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012 + kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013 + kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014 + kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015 + kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016 + kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017 + kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018 + kGULNetworkMessageCodeURLSession019 = 901019, // I-NET901019 +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h new file mode 100644 index 0000000..3f9f7f9 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkLoggerProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSError *_Nullable error); +typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSString *sessionID, + NSError *_Nullable error); +typedef void (^GULNetworkSystemCompletionHandler)(void); + +/// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses. +@interface GULNetworkURLSession : NSObject + +/// Indicates whether the background network is enabled. Default value is NO. +@property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled; + +/// The logger delegate to log message, errors or warnings that occur during the network operations. +@property(nonatomic, weak, nullable) id loggerDelegate; + +/// Calls the system provided completion handler after the background session is finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Initializes with logger delegate. +- (instancetype)initWithNetworkLoggerDelegate: + (nullable id)networkLoggerDelegate NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Sends an asynchronous POST request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session/connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +/// Sends an asynchronous GET request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +NS_ASSUME_NONNULL_END +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h new file mode 100644 index 0000000..8883c4d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, + const char *host); + +typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callback, + SCNetworkReachabilityContext *context); +typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); +typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); + +typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf); + +struct GULReachabilityApi { + GULReachabilityCreateWithNameFn createWithNameFn; + GULReachabilitySetCallbackFn setCallbackFn; + GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn; + GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn; + GULReachabilityReleaseFn releaseFn; +}; + +@interface GULReachabilityChecker (Internal) + +- (const struct GULReachabilityApi *)reachabilityApi; +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m new file mode 100644 index 0000000..1ddacdf --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m @@ -0,0 +1,240 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GULReachabilityChecker+Internal.h" +#import "Private/GULReachabilityChecker.h" +#import "Private/GULReachabilityMessageCode.h" + +#import +#import + +static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; + +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +static const struct GULReachabilityApi kGULDefaultReachabilityApi = { + SCNetworkReachabilityCreateWithName, + SCNetworkReachabilitySetCallback, + SCNetworkReachabilityScheduleWithRunLoop, + SCNetworkReachabilityUnscheduleFromRunLoop, + CFRelease, +}; + +static NSString *const kGULReachabilityUnknownStatus = @"Unknown"; +static NSString *const kGULReachabilityConnectedStatus = @"Connected"; +static NSString *const kGULReachabilityDisconnectedStatus = @"Disconnected"; + +@interface GULReachabilityChecker () + +@property(nonatomic, assign) const struct GULReachabilityApi *reachabilityApi; +@property(nonatomic, assign) GULReachabilityStatus reachabilityStatus; +@property(nonatomic, copy) NSString *host; +@property(nonatomic, assign) SCNetworkReachabilityRef reachability; + +@end + +@implementation GULReachabilityChecker + +@synthesize reachabilityApi = reachabilityApi_; +@synthesize reachability = reachability_; + +- (const struct GULReachabilityApi *)reachabilityApi { + return reachabilityApi_; +} + +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi { + if (reachability_) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode000], + @"Cannot change reachability API while reachability is running. " + @"Call stop first."); + return; + } + reachabilityApi_ = reachabilityApi; +} + +@synthesize reachabilityStatus = reachabilityStatus_; +@synthesize host = host_; +@synthesize reachabilityDelegate = reachabilityDelegate_; + +- (BOOL)isActive { + return reachability_ != nil; +} + +- (void)setReachabilityDelegate:(id)reachabilityDelegate { + if (reachabilityDelegate && + (![(NSObject *)reachabilityDelegate conformsToProtocol:@protocol(GULReachabilityDelegate)])) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULReachabilityMessageCode005], + @"Reachability delegate doesn't conform to Reachability protocol."); + return; + } + reachabilityDelegate_ = reachabilityDelegate; +} + +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host { + self = [super init]; + + if (!host || !host.length) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode001], + @"Invalid host specified"); + return nil; + } + if (self) { + [self setReachabilityDelegate:reachabilityDelegate]; + reachabilityApi_ = &kGULDefaultReachabilityApi; + reachabilityStatus_ = kGULReachabilityUnknown; + host_ = [host copy]; + reachability_ = nil; + } + return self; +} + +- (void)dealloc { + reachabilityDelegate_ = nil; + [self stop]; +} + +- (BOOL)start { + if (!reachability_) { + reachability_ = reachabilityApi_->createWithNameFn(kCFAllocatorDefault, [host_ UTF8String]); + if (!reachability_) { + return NO; + } + SCNetworkReachabilityContext context = { + 0, /* version */ + (__bridge void *)(self), /* info (passed as last parameter to reachability callback) */ + NULL, /* retain */ + NULL, /* release */ + NULL /* copyDescription */ + }; + if (!reachabilityApi_->setCallbackFn(reachability_, ReachabilityCallback, &context) || + !reachabilityApi_->scheduleWithRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes)) { + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode002], + @"Failed to start reachability handle"); + return NO; + } + } + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode003], + @"Monitoring the network status"); + return YES; +} + +- (void)stop { + if (reachability_) { + reachabilityStatus_ = kGULReachabilityUnknown; + reachabilityApi_->unscheduleFromRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes); + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + } +} + +- (GULReachabilityStatus)statusForFlags:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = kGULReachabilityNotReachable; + // If the Reachable flag is not set, we definitely don't have connectivity. + if (flags & kSCNetworkReachabilityFlagsReachable) { + // Reachable flag is set. Check further flags. + if (!(flags & kSCNetworkReachabilityFlagsConnectionRequired)) { +// Connection required flag is not set, so we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } else if ((flags & (kSCNetworkReachabilityFlagsConnectionOnDemand | + kSCNetworkReachabilityFlagsConnectionOnTraffic)) && + !(flags & kSCNetworkReachabilityFlagsInterventionRequired)) { +// If the connection on demand or connection on traffic flag is set, and user intervention +// is not required, we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } + } + return status; +} + +- (void)reachabilityFlagsChanged:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = [self statusForFlags:flags]; + if (reachabilityStatus_ != status) { + NSString *reachabilityStatusString; + if (status == kGULReachabilityUnknown) { + reachabilityStatusString = kGULReachabilityUnknownStatus; + } else { + reachabilityStatusString = (status == kGULReachabilityNotReachable) + ? kGULReachabilityDisconnectedStatus + : kGULReachabilityConnectedStatus; + } + + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode004], + @"Network status has changed. Code:%@, status:%@", @(status), + reachabilityStatusString); + reachabilityStatus_ = status; + [reachabilityDelegate_ reachability:self statusChanged:reachabilityStatus_]; + } +} + +@end + +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GULReachabilityChecker *checker = (__bridge GULReachabilityChecker *)info; + [checker reachabilityFlagsChanged:flags]; +} + +// This function used to be at the top of the file, but it was moved here +// as a workaround for a suspected compiler bug. When compiled in Release mode +// and run on an iOS device with WiFi disabled, the reachability code crashed +// when calling SCNetworkReachabilityScheduleWithRunLoop, or shortly thereafter. +// After unsuccessfully trying to diagnose the cause of the crash, it was +// discovered that moving this function to the end of the file magically fixed +// the crash. If you are going to edit this file, exercise caution and make sure +// to test thoroughly with an iOS device under various network conditions. +const NSString *GULReachabilityStatusString(GULReachabilityStatus status) { + switch (status) { + case kGULReachabilityUnknown: + return @"Reachability Unknown"; + + case kGULReachabilityNotReachable: + return @"Not reachable"; + + case kGULReachabilityViaWifi: + return @"Reachable via Wifi"; + + case kGULReachabilityViaCellular: + return @"Reachable via Cellular Data"; + + default: + return [NSString stringWithFormat:@"Invalid reachability status %d", (int)status]; + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h new file mode 100644 index 0000000..b317a0b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Reachability Status +typedef enum { + kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable. + kGULReachabilityNotReachable, ///< Host is not reachable. + kGULReachabilityViaWifi, ///< Host is reachable via Wifi. + kGULReachabilityViaCellular, ///< Host is reachable via cellular. +} GULReachabilityStatus; + +const NSString *GULReachabilityStatusString(GULReachabilityStatus status); + +@class GULReachabilityChecker; + +/// Google Analytics iOS Reachability Checker. +@protocol GULReachabilityDelegate +@required +/// Called when network status has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status; +@end + +/// Google Analytics iOS Network Status Checker. +@interface GULReachabilityChecker : NSObject + +/// The last known reachability status, or GULReachabilityStatusUnknown if the +/// checker is not active. +@property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus; +/// The host to which reachability status is to be checked. +@property(nonatomic, copy, readonly) NSString *host; +/// The delegate to be notified of reachability status changes. +@property(nonatomic, weak) id reachabilityDelegate; +/// `YES` if the reachability checker is active, `NO` otherwise. +@property(nonatomic, readonly) BOOL isActive; + +/// Initialize the reachability checker. Note that you must call start to begin checking for and +/// receiving notifications about network status changes. +/// +/// @param reachabilityDelegate The delegate to be notified when reachability status to host +/// changes. +/// +/// @param host The name of the host. +/// +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host; + +- (instancetype)init NS_UNAVAILABLE; + +/// Start checking for reachability to the specified host. This has no effect if the status +/// checker is already checking for connectivity. +/// +/// @return `YES` if initiating status checking was successful or the status checking has already +/// been initiated, `NO` otherwise. +- (BOOL)start; + +/// Stop checking for reachability to the specified host. This has no effect if the status +/// checker is not checking for connectivity. +- (void)stop; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h new file mode 100644 index 0000000..283cdd5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULReachabilityMessageCode) { + // GULReachabilityChecker.m + kGULReachabilityMessageCode000 = 902000, // I-NET902000 + kGULReachabilityMessageCode001 = 902001, // I-NET902001 + kGULReachabilityMessageCode002 = 902002, // I-NET902002 + kGULReachabilityMessageCode003 = 902003, // I-NET902003 + kGULReachabilityMessageCode004 = 902004, // I-NET902004 + kGULReachabilityMessageCode005 = 902005, // I-NET902005 + kGULReachabilityMessageCode006 = 902006, // I-NET902006 +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m new file mode 100644 index 0000000..ac497b2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m @@ -0,0 +1,235 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULUserDefaults.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +static NSTimeInterval const kGULSynchronizeInterval = 1.0; + +static NSString *const kGULLogFormat = @"I-GUL%06ld"; + +static GULLoggerService kGULLogUserDefaultsService = @"[GoogleUtilities/UserDefaults]"; + +typedef NS_ENUM(NSInteger, GULUDMessageCode) { + GULUDMessageCodeInvalidKeyGet = 1, + GULUDMessageCodeInvalidKeySet = 2, + GULUDMessageCodeInvalidObjectSet = 3, + GULUDMessageCodeSynchronizeFailed = 4, +}; + +@interface GULUserDefaults () + +/// Equivalent to the suite name for NSUserDefaults. +@property(readonly) CFStringRef appNameRef; + +@property(atomic) BOOL isPreferenceFileExcluded; + +@end + +@implementation GULUserDefaults { + // The application name is the same with the suite name of the NSUserDefaults, and it is used for + // preferences. + CFStringRef _appNameRef; +} + ++ (GULUserDefaults *)standardUserDefaults { + static GULUserDefaults *standardUserDefaults; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[GULUserDefaults alloc] init]; + }); + return standardUserDefaults; +} + +- (instancetype)init { + return [self initWithSuiteName:nil]; +} + +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName { + self = [super init]; + + NSString *name = [suiteName copy]; + + if (self) { + // `kCFPreferencesCurrentApplication` maps to the same defaults database as + // `[NSUserDefaults standardUserDefaults]`. + _appNameRef = + name.length ? (__bridge_retained CFStringRef)name : kCFPreferencesCurrentApplication; + } + + return self; +} + +- (void)dealloc { + // If we're using a custom `_appNameRef` it needs to be released. If it's a constant, it shouldn't + // need to be released since we don't own it. + if (CFStringCompare(_appNameRef, kCFPreferencesCurrentApplication, 0) != kCFCompareEqualTo) { + CFRelease(_appNameRef); + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; +} + +- (nullable id)objectForKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(@"", NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeyGet], + @"Cannot get object for invalid user default key."); + return nil; + } + return (__bridge_transfer id)CFPreferencesCopyAppValue((__bridge CFStringRef)key, _appNameRef); +} + +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeySet], + @"Cannot set object for invalid user default key."); + return; + } + if (!value) { + CFPreferencesSetAppValue((__bridge CFStringRef)key, NULL, _appNameRef); + [self scheduleSynchronize]; + return; + } + BOOL isAcceptableValue = + [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] || + [value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] || + [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]]; + if (!isAcceptableValue) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidObjectSet], + @"Cannot set invalid object to user defaults. Must be a string, number, array, " + @"dictionary, date, or data. Value: %@", + value); + return; + } + + CFPreferencesSetAppValue((__bridge CFStringRef)key, (__bridge CFStringRef)value, _appNameRef); + [self scheduleSynchronize]; +} + +- (void)removeObjectForKey:(NSString *)key { + [self setObject:nil forKey:key]; +} + +#pragma mark - Getters + +- (NSInteger)integerForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.integerValue; +} + +- (float)floatForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.floatValue; +} + +- (double)doubleForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.doubleValue; +} + +- (BOOL)boolForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.boolValue; +} + +- (nullable NSString *)stringForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSArray *)arrayForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +#pragma mark - Setters + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)defaultName { + [self setObject:@(integer) forKey:defaultName]; +} + +- (void)setFloat:(float)value forKey:(NSString *)defaultName { + [self setObject:@(value) forKey:defaultName]; +} + +- (void)setDouble:(double)doubleNumber forKey:(NSString *)defaultName { + [self setObject:@(doubleNumber) forKey:defaultName]; +} + +- (void)setBool:(BOOL)boolValue forKey:(NSString *)defaultName { + [self setObject:@(boolValue) forKey:defaultName]; +} + +#pragma mark - Save data + +- (void)synchronize { + if (!CFPreferencesAppSynchronize(_appNameRef)) { + GULLogError(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeSynchronizeFailed], + @"Cannot synchronize user defaults to disk"); + } +} + +#pragma mark - Private methods + +/// Removes all values from the search list entry specified by 'domainName', the current user, and +/// any host. The change is persistent. Equivalent to -removePersistentDomainForName: of +/// NSUserDefaults. +- (void)clearAllData { + // On macOS, using `kCFPreferencesCurrentHost` will not set all the keys necessary to match + // `NSUserDefaults`. +#if TARGET_OS_OSX + CFStringRef host = kCFPreferencesAnyHost; +#else + CFStringRef host = kCFPreferencesCurrentHost; +#endif // TARGET_OS_OSX + + CFArrayRef keyList = CFPreferencesCopyKeyList(_appNameRef, kCFPreferencesCurrentUser, host); + if (!keyList) { + return; + } + + CFPreferencesSetMultiple(NULL, keyList, _appNameRef, kCFPreferencesCurrentUser, host); + CFRelease(keyList); + [self scheduleSynchronize]; +} + +- (void)scheduleSynchronize { + // Synchronize data using a timer so that multiple set... calls can be coalesced under one + // synchronize. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; + // This method may be called on multiple queues (due to set... methods can be called on any queue) + // synchronize can be scheduled on different queues, so make sure that it does not crash. If this + // instance goes away, self will be released also, no one will retain it and the schedule won't be + // called. + [self performSelector:@selector(synchronize) withObject:nil afterDelay:kGULSynchronizeInterval]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h new file mode 100644 index 0000000..0d04781 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A thread-safe user defaults that uses C functions from CFPreferences.h instead of +/// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a +/// background thread to avoid crashing. // TODO: Insert radar number here. +@interface GULUserDefaults : NSObject + +/// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same +/// data of the standardUserDefaults. ++ (GULUserDefaults *)standardUserDefaults; + +/// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name. +/// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly +/// the same. +/// +/// @param suiteName The name of the suite of the user defaults. +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName; + +#pragma mark - Getters + +/// Searches the receiver's search list for a default with the key 'defaultName' and return it. If +/// another process has changed defaults in the search list, NSUserDefaults will automatically +/// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults +/// Configuration File, the latest value may not be immediately available, and the registered value +/// will be returned instead. +- (nullable id)objectForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray. +- (nullable NSArray *)arrayForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value +/// is not an NSDictionary. +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString +/// representation. If a non-string non-number value is found, nil will be returned. +- (nullable NSString *)stringForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the +/// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, +/// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted +/// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 +/// will be returned. +- (NSInteger)integerForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a float, and boolean values will not be +/// converted. +- (float)floatForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a double, and boolean values will not be +/// converted. +- (double)doubleForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value +/// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an +/// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string +/// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned. +- (BOOL)boolForKey:(NSString *)defaultName; + +#pragma mark - Setters + +/// Immediately stores a value (or removes the value if `nil` is passed as the value) for the +/// provided key in the search list entry for the receiver's suite name in the current user and any +/// host, then asynchronously stores the value persistently, where it is made available to other +/// processes. +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber. +- (void)setFloat:(float)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a double to an +/// NSNumber. +- (void)setDouble:(double)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an +/// NSNumber. +- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber. +- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; + +#pragma mark - Removing Defaults + +/// Equivalent to -[... setObject:nil forKey:defaultName] +- (void)removeObjectForKey:(NSString *)defaultName; + +#pragma mark - Save data + +/// Blocks the calling thread until all in-progress set operations have completed. +- (void)synchronize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/README.md new file mode 100644 index 0000000..907e2a9 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/GoogleUtilities/README.md @@ -0,0 +1,213 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +This command will get the right `clang-format` version: + +`brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on +macOS and tvOS. FirebaseMessaging is available for tvOS. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +Note that the Firebase pod is not available for macOS and tvOS. + +To install, add a subset of the following to the Podfile: + +``` +pod 'FirebaseAuth' +pod 'FirebaseCore' +pod 'FirebaseDatabase' +pod 'FirebaseFirestore' # Only iOS and macOS +pod 'FirebaseFunctions' +pod 'FirebaseMessaging' # Only iOS and tvOS +pod 'FirebaseStorage' +``` + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGBugReporting.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGBugReporting.h new file mode 100644 index 0000000..c587b95 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGBugReporting.h @@ -0,0 +1,194 @@ +// +// IBGBugReporting.h +// InstabugBugReporting +// +// Created by Yousef Hamza on 5/17/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import +#import "IBGTypes.h" + +NS_SWIFT_NAME(BugReporting) +@interface IBGBugReporting : NSObject + +/** + @brief Acts as master switch for the Bug Reporting. + + @discussion It's enabled by default. When disabled, both "Report a problem" and "Suggest an improvement" will be removed from Instabug Prompt Options. In addition, when disabled +showWithReportType:options: won’t have an effect. + */ +@property (class, atomic, assign) BOOL enabled; + +/** + @brief Sets a block of code to be executed just before the SDK's UI is presented. + + @discussion This block is executed on the UI thread. Could be used for performing any UI changes before the SDK's UI + is shown. + */ +@property(class, atomic, strong) void(^willInvokeHandler)(void); + +/** + @brief Sets a block of code to be executed right after the SDK's UI is dismissed. + + @discussion This block is executed on the UI thread. Could be used for performing any UI changes after the SDK's UI + is dismissed. + + The block has the following parameters: + + - dismissType: How the SDK was dismissed. + - reportType: Type of report that has been sent. Will be set to IBGReportTypeBug in case the SDK has been dismissed + without selecting a report type, so you might need to check dismissType before reportType. + + @see IBGReportType, IBGDismissType + */ +@property(class, atomic, strong) void(^didDismissHandler)(IBGDismissType dismissType, IBGReportType reportType); + +/** + @brief Sets a block of code to be executed when a prompt option is selected + + @param didSelectPromptOptionHandler A block of code that gets executed when a prompt option is selected. + + The block has the following parameters: + - prompOption: The option selected in prompt. + */ +@property(class, atomic, strong) void(^didSelectPromptOptionHandler)(IBGPromptOption promptOption); + +/** + @brief Sets the events that invoke the feedback form. + + @discussion Default is set by `startWithToken:invocationEvent:`. + + @see IBGInvocationEvent + */ +@property(class, atomic, assign) IBGInvocationEvent invocationEvents; + +/** + @brief Sets the threshold value of the shake gesture for iPhone/iPod Touch. + + @discussion Default for iPhone is 2.5. The lower the threshold, the easier it will be to invoke Instabug with the + shake gesture. A threshold which is too low will cause Instabug to be invoked unintentionally. + */ +@property(class, atomic, assign) CGFloat shakingThresholdForiPhone; + +/** + @brief Sets the threshold value of the shake gesture for iPad. + + @discussion Default for iPad is 0.6. The lower the threshold, the easier it will be to invoke Instabug with the + shake gesture. A threshold which is too low will cause Instabug to be invoked unintentionally. + */ +@property(class, atomic, assign) CGFloat shakingThresholdForiPad; + +/** + @brief Sets the default edge at which the floating button will be shown. Different orientations are already handled. + + @discussion Default for `floatingButtonEdge` is `CGRectMaxXEdge`. + */ +@property(class, atomic, assign) CGRectEdge floatingButtonEdge; + +/** + @brief Sets the default offset from the top at which the floating button will be shown. + + @discussion Default for `floatingButtonOffsetFromTop` is 50 + */ +@property(class, atomic, assign) CGFloat floatingButtonTopOffset; + +/** + @brief Sets whether attachments in bug reporting and in-app messaging are enabled. + */ +@property(class, atomic, assign) IBGAttachmentType enabledAttachmentTypes; + +/** + @brief Controls if Instabug Prompt Options should contain "Report a problem” and/or "Suggest an improvement" or not. + + @discussion By default, both options are enabled. + */ +@property(class, atomic, assign) IBGBugReportingReportType promptOptionsEnabledReportTypes; + +/** + @brief Sets whether the extended bug report mode should be disabled, enabled with required fields or enabled with optional fields. + + @discussion This feature is disabled by default. When enabled, it adds more fields for your reporters to fill in. You can set whether the extra fields are required or optional. + 1. Expected Results. + 2. Actual Results. + 3. Steps to Reproduce. + + An enum to disable the extended bug report mode, enable it with required or with optional fields. + */ +@property(class, atomic, assign) IBGExtendedBugReportMode extendedBugReportMode; + +/** + @brief Use to specify different options that would affect how Instabug is shown and other aspects about the reporting experience. + + @discussion See IBGInvocationOptions. + */ +@property(class, atomic, assign) IBGBugReportingOption bugReportingOptions; + +/** + @brief Sets the default position at which the Instabug screen recording button will be shown. Different orientations are already handled. + + @discussion Default for `position` is `bottomRight`. + */ +@property(class, atomic, assign) IBGPosition videoRecordingFloatingButtonPosition; + +/** + @method +showWithReportType:options: + @brief Shows the compose view of a bug report or a feedback. + + @see IBGBugReportingReportType + @see IBGBugReportingOption + */ ++ (void)showWithReportType:(IBGBugReportingReportType)reportType + options:(IBGBugReportingOption)options; + +/** + @brief Dismisses any Instabug views that are currently being shown. + */ ++ (void)dismiss; + +/** + @brief Enables/disables inspect view hierarchy when reporting a bug/feedback. + */ +@property (class, atomic, assign) BOOL shouldCaptureViewHierarchy; + +/** + @brief Sets whether the SDK is recording the screen or not. + + @discussion Enabling auto screen recording would give you an insight on the scenario a user has performed before encountering a bug. screen recording is attached with each bug being sent. + + Auto screen recording is disabled by default. + */ +@property (class, atomic, assign) BOOL autoScreenRecordingEnabled; + +/** + @brief Sets maximum auto screen recording video duration. + + @discussion sets maximum auto screen recording video duration with max value 30 seconds and min value greater than 1 sec. + */ +@property (class, atomic, assign) CGFloat autoScreenRecordingDuration; + +/* + +------------------------------------------------------------------------+ + | Deprecated APIs | + +------------------------------------------------------------------------+ + | The following section includes all deprecated APIs. | + | | + | We've made a few changes to our APIs starting from version 8.0 to make | + | them more intuitive and easily reachable. | + | | + | While the APIs below still function, they will be completely removed | + | in a future release. | + | | + | To adopt the new changes, please refer to our migration guide at: | + | https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide | + +------------------------------------------------------------------------+ + */ + ++ (void)invoke DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-invoke for instructions on migrating to SDK v8.1 APIs."); + ++ (void)invokeWithMode:(IBGInvocationMode)invocationMode options:(IBGBugReportingInvocationOption)options DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-invokewithmode for instructions on migrating to SDK v8.1 APIs."); + +@property(class, atomic, assign) IBGPromptOption promptOptions DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-promptoptions for instructions on migrating to SDK v8.1 APIs."); + +@property(class, atomic, assign) IBGBugReportingInvocationOption invocationOptions DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-invocationoptions for instructions on migrating to SDK v8.1 APIs."); + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGChats.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGChats.h new file mode 100644 index 0000000..7c28366 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGChats.h @@ -0,0 +1,29 @@ +// +// IBGChats.h +// InstabugChats +// +// Created by Hassaan El-Garem on 11/25/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import + +NS_SWIFT_NAME(Chats) +@interface IBGChats : NSObject + +/** + @brief Acts as master switch for the In-app Chats. + + @discussion It's enabled by default. When disabled, the user can't start a new chat from the SDK, the “Ask a question” option is removed from Instabug Prompt Options, and the compose button is removed from the chats list. In addition, when disabled +showWithChatsList: won’t have an effect. +*/ +@property (class, atomic, assign) BOOL enabled; + +/** + @method +show: + @brief Shows the compose new chat view. + + @discussion In order to show the chats list, [IBGReplies show] should be used. + */ ++ (void)show; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGCrashReporting.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGCrashReporting.h new file mode 100644 index 0000000..2338024 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGCrashReporting.h @@ -0,0 +1,30 @@ +// +// IBGCrashReporting.h +// InstabugCrashReporting +// +// Created by Yousef Hamza on 5/17/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import + +NS_SWIFT_NAME(CrashReporting) +@interface IBGCrashReporting : NSObject + +@property (class, atomic, assign) BOOL enabled; + +/** + @brief Report an exception manually. + + @param exception Exception to be reported. + */ ++ (void)reportException:(NSException *)exception; + +/** + @brief Report an error manually. + + @param error error to be reported. + */ ++ (void)reportError:(NSError *)error; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGFeatureRequests.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGFeatureRequests.h new file mode 100644 index 0000000..5921dc5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGFeatureRequests.h @@ -0,0 +1,37 @@ +// +// IBGFeatureRequests.h +// Instabug +// +// Created by Yousef Hamza on 5/17/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import +#import "IBGTypes.h" + +NS_SWIFT_NAME(FeatureRequests) +@interface IBGFeatureRequests : NSObject + +/** + @brief Acts as a master switch for the Feature Requests. + + @discussion It's enabled by default. When disabled, all the functionalities related to the Feature Requests is disabled. + */ +@property (class, atomic, assign) BOOL enabled; + +/** + @brief Sets whether users are required to enter an email address or not when doing a certain action `IBGAction`. + + @discussion Defaults to YES. + + @param isEmailFieldRequired A boolean to indicate whether email field is required or not. + @param actionType An enum that indicates which action types will have the isEmailFieldRequired. + */ ++ (void)setEmailFieldRequired:(BOOL)isEmailFieldRequired forAction:(IBGAction)actionType; + +/** + @brief Shows the UI for feature requests list + */ ++ (void)show; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGLog.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGLog.h new file mode 100644 index 0000000..2a0db99 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGLog.h @@ -0,0 +1,148 @@ +// +// IBGLog.h +// InstabugI +// +// Created by Yousef Hamza on 5/17/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import +#import "InstabugCore.h" + +@interface IBGLog : NSObject + +@property (class, atomic, assign) BOOL printsToConsole; + +/** + @brief Adds custom logs that will be sent with each report. Logs are added with the debug log level. + + @param log Message to be logged. + */ ++ (void)log:(NSString *)log; + +/** + @brief Adds custom logs with the verbose log level. Logs will be sent with each report. + + @param log Message to be logged. + */ ++ (void)logVerbose:(NSString *)log; + +/** + @brief Adds custom logs with the debug log level. Logs will be sent with each report. + + @param log Message to be logged. + */ ++ (void)logDebug:(NSString *)log; + +/** + @brief Adds custom logs with the info log level. Logs will be sent with each report. + + @param log Message to be logged. + */ ++ (void)logInfo:(NSString *)log; + +/** + @brief Adds custom logs with the warn log level. Logs will be sent with each report. + + @param log Message to be logged. + */ ++ (void)logWarn:(NSString *)log; + +/** + @brief Adds custom logs with the error log level. Logs will be sent with each report. + + @param log Message to be logged. + */ ++ (void)logError:(NSString *)log; + +/** + @brief Clear all Logs. + + @discussion Clear all Instabug logs, console logs, network logs and user steps. + + */ ++ (void)clearAllLogs; + +/** + @brief Adds custom logs that will be sent with each report. + + @discussion Can be used in a similar fashion to NSLog. Logs are added with the debug log level. + For usage in Swift, see `Instabug.ibgLog()`. + + @param format Format string. + @param ... Optional varargs arguments. + */ +OBJC_EXTERN void InstabugLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); + +/** + @brief Adds custom logs with the verbose log level. Logs will be sent with each report. + + @discussion Can be used in a similar fashion to NSLog. For usage in Swift, see `Instabug.logVerbose()`. + + @param format Format string. + @param ... Optional varargs arguments. + */ +OBJC_EXTERN void IBGLogVerbose(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); + +/** + @brief Adds custom logs with the debug log level. Logs will be sent with each report. + + @discussion Can be used in a similar fashion to NSLog. For usage in Swift, see `Instabug.logDebug()`. + + @param format Format string. + @param ... Optional varargs arguments. + */ +OBJC_EXTERN void IBGLogDebug(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); + +/** + @brief Adds custom logs with the info log level. Logs will be sent with each report. + + @discussion Can be used in a similar fashion to NSLog. For usage in Swift, see `Instabug.logInfo()`. + + @param format Format string. + @param ... Optional varargs arguments. + */ +OBJC_EXTERN void IBGLogInfo(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); + +/** + @brief Adds custom logs with the warn log level. Logs will be sent with each report. + + @discussion Can be used in a similar fashion to NSLog. For usage in Swift, see `Instabug.logWarn()`. + + @param format Format string. + @param ... Optional varargs arguments. + */ +OBJC_EXTERN void IBGLogWarn(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); + +/** + @brief Adds custom logs with the error log level. Logs will be sent with each report. + + @discussion Can be used in a similar fashion to NSLog. For usage in Swift, see `Instabug.logError()`. + + @param format Format string. + @param ... Optional varargs arguments. + */ +OBJC_EXTERN void IBGLogError(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2) ; + +/** + @brief Used to reroute all your NSLogs to Instabug to be able to automatically include them with reports. + + @discussion For details on how to reroute your NSLogs to Instabug, see https://docs.instabug.com/docs/ios-logging + + @param format Format string. + @param args Arguments list. + */ +OBJC_EXTERN void IBGNSLog(NSString *format, va_list args); + +/** + @brief Used to reroute all your NSLogs to Instabug with their log level to be able to automatically include them with reports. + + @discussion For details on how to reroute your NSLogs to Instabug, see https://docs.instabug.com/docs/ios-logging + + @param format Format string. + @param args Arguments list. + @param logLevel log level. + */ +OBJC_EXTERN void IBGNSLogWithLevel(NSString *format, va_list args, IBGLogLevel logLevel); + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGNetworkLogger.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGNetworkLogger.h new file mode 100644 index 0000000..4963cfd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGNetworkLogger.h @@ -0,0 +1,113 @@ +// +// IBGNetworkLogger.h +// InstabugCore +// +// Created by Yousef Hamza on 5/17/18. +// Copyright © 2018 Instabug. All rights reserved. +// + +#import +#import "IBGTypes.h" + +NS_SWIFT_NAME(NetworkLogger) +@interface IBGNetworkLogger : NSObject + +@property (class, atomic, assign) BOOL enabled; + +/** + @brief Enable logging for network requests and responses on a custom NSURLSessionConfiguration. + + @discussion Logging for network requests and responses may not work if you're using a custom `NSURLSession` object. + If this is the case, call this method passing in your custom NSURLSessions's configuration to enable logging for it. + + @param URLSessionConfiguration The NSURLSessionConfiguration of your custom NSURLSession. + */ ++ (void)enableLoggingForURLSessionConfiguration:(NSURLSessionConfiguration *_Nonnull)URLSessionConfiguration; + + +/** + @brief Use to obfuscate a request that's going to be included in network logs. + + @discussion Use this method if you want to make any modifications to requests before it is added to the network log. + This won't be applied to already filtered requests + + Note that thsese changes doesn't affect the actual request. + + The provided block will be called for every request. You should do whatever processing you need to do on the request inside + that block, then return a request to be included in network logs. + + This method usage overrides modifications made by `setNetworkLoggingURLObfuscationHandler:`. + + @param obfuscationHandler A block that takes a request and returns a new modified one to be logged.. + */ ++ (void)setRequestObfuscationHandler:(nonnull NSURLRequest * _Nonnull (^)(NSURLRequest * _Nonnull request))obfuscationHandler; + +/** + @brief Use to obfuscate a request's response that's going to be included in network logs. + + @discussion Use this method if you want to make any modifications to a request's respone and its data before it's + added to network logs. + + The provided block will be called for every response. You should do whatever processing you need to do on the response + and data inside that block, then return response and data to be included in network logs. Changes you make to the + response and its data only affect network logs, not the actual response. + + @param obfuscationHandler A block that takes the original response, its data and a return block as parameters. The + return block should be called with the modified data and response. + */ ++ (void)setResponseObfuscationHandler:(void (^_Nonnull)(NSData * _Nullable responseData, NSURLResponse * _Nonnull response, NetworkObfuscationCompletionBlock _Nonnull returnBlock))obfuscationHandler; + +/** + @brief Use to get callbacks about progress of sending body content of a particular request when networking logging is + enabled. + + @discussion The provided block will get periodical callbacks about the progress of sending the body content of a request. + + @param URL URL which will be attached with requestProgressHandler. + @param requestProgressHandler A block that will be called for the requestURL when SDK intercept that request. + + */ ++ (void)setProgressHandlerForRequestURL:(nonnull NSURL *)URL + progressHandler:(nonnull void (^)(NSURLSessionTask * _Nonnull task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))requestProgressHandler; + + +/** + @brief Used to ask whether your app is prepared to handle a particular authentication challenge. Can be called on any thread. + + @discussion Set this block if your app implements SSL pinning and you have network logging enabled. + + @param protectionSpaceHandler A block that takes the protection space for the authentication challenge and should return + true or false. + */ ++ (void)setCanAuthenticateAgainstProtectionSpaceHandler:(BOOL(^_Nonnull)(NSURLProtectionSpace * _Nonnull protectionSpace))protectionSpaceHandler; + + +/** + @brief Used to process an authentication challenge and return an NSURLCredential object. + + @discussion Set this block if your app implements SSL pinning and you have network logging enabled. + + @param reciveChallengeHandler A block that takes the authentication challenge and returns NSURLCredential. + */ ++ (void)setDidReceiveAuthenticationChallengeHandler:(NSURLCredential* _Nonnull (^_Nonnull)(NSURLAuthenticationChallenge * _Nonnull challenge))reciveChallengeHandler; + + +/** + @brief Specify NSPredicates to be used to omit certain network requests from being logged based on their request or + response objects. + + @discussion `requestFilterPredicate` will be matched against an `NSURLRequest`. It can be used to filter out requests + to a specific domain for example. + + `responseFilterPredicate` will be matched against an `NSHTTPURLResponse`. It can be used to filter out responses that + match specific status codes. + + If both predicates are specified, `requestFilterPredicate` is evaluated first, if it matches, the request is omitted + from logging without evaluating `responseFilterPredicate`. + + @param requestFilterPredicate An NSPredicate to match against an NSURLRequest. Matching requests will be omitted. + @param responseFilterPredicate An NSPredicate to match against an NSHTTPURLResponse. Matching responses will be omitted. + */ ++ (void)setNetworkLoggingRequestFilterPredicate:(nullable NSPredicate *)requestFilterPredicate responseFilterPredicate:(nullable NSPredicate *)responseFilterPredicate; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGReplies.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGReplies.h new file mode 100644 index 0000000..5e3e346 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGReplies.h @@ -0,0 +1,93 @@ +// +// IBGReplies.h +// InstabugChats +// +// Created by Hassaan El-Garem on 11/25/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import + +NS_SWIFT_NAME(Replies) +@interface IBGReplies : NSObject + +/** + @brief Acts as a master switch for the In-app Replies. + + @discussion It's enabled by default. When disabled, the user can’t reach the chats history from the SDK. The chats list button is removed from Instabug Prompt Options. In addition, when disabled the in-app notification as well as the push notifications are disabled. And, +show won’t have an effect. + */ +@property (class, atomic, assign) BOOL enabled; + +/** + @brief Sets a block of code that gets executed when a new message is received. + */ +@property (class, atomic, strong) void (^didReceiveReplyHandler)(void); + +/** + @brief Enables/disables showing in-app notifications when the user receives a new message. + */ +@property (class, atomic, assign) BOOL inAppNotificationsEnabled; + +/** + @brief Enables/disables the use of push notifications in the SDK. + + @discussion In order to enable push notifications, implement + `-[UIApplicationDelegate application:didRegisterForRemoteNotificationsWithDeviceToken:]` and either + `-[UIApplicationDelegate application:didReceiveRemoteNotification]` or + `-[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:]`. + + Defaults to YES. + */ +@property (class, atomic, assign) BOOL pushNotificationsEnabled; + +/** + @brief Returns the number of unread messages the user currently has. + + @discussion Use this method to get the number of unread messages the user has, then possibly notify them about it with + your own UI. + + @return Notifications count, or -1 incase the SDK has not been initialized. + */ +@property (class, atomic, assign, readonly) NSInteger unreadRepliesCount; + +/** + @method +show + @brief Shows the chats list. + + @discussion It shows the chats list only if the user has a chats history. Use +hasChats to know if a user has chats history or not. */ ++ (void)show; + +/** + @method +hasChats + @brief To know if a user already has a chats history or not. + + @discussion Use it before calling show. + */ ++ (BOOL)hasChats; + +/** + @brief Call this method and pass the notification's userInfo dictionary to allow Instabug to handle its remote notifications. + + @discussion Instabug will check if notification is from Instabug's servers and only handle it if it is. + You should call this method in -[UIApplicationDelegate application:didReceiveRemoteNotification:] and pass received userInfo + dictionary, or `-[UIApplicationDelegate application:didFinishLaunchingWithOptions:]` and pass + `[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]`. + + @param userInfo userInfo dictionary from `-[UIApplicationDelegate application:didReceiveRemoteNotification:]` or + `[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]` from + `-[UIApplicationDelegate application:didFinishLaunchingWithOptions:]`. + */ ++ (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo; + +/** + @brief Use this method to set Apple Push Notification token to enable receiving Instabug push notifications. + + @discussion You should call this method after receiving token in + `-[UIApplicationDelegate didRegisterForRemoteNotificationsWithDeviceToken:]` and pass received token. + + @param deviceToken Device token received in `-[UIApplicationDelegate didRegisterForRemoteNotificationsWithDeviceToken:]` + */ ++ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; + + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGReport.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGReport.h new file mode 100644 index 0000000..f304685 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGReport.h @@ -0,0 +1,31 @@ +// +// IBGReport.h +// InstabugCore +// +// Created by khaled mohamed el morabea on 1/21/18. +// Copyright © 2018 Instabug. All rights reserved. +// + +#import + +@interface IBGReport : NSObject + +@property (nonatomic, copy, readonly) NSArray *tags; +@property (nonatomic, copy, readonly) NSArray *instabugLogs; +@property (nonatomic, copy, readonly) NSArray *consoleLogs; +@property (nonatomic, copy, readonly) NSDictionary *userAttributes; +@property (nonatomic, copy, readonly) NSArray *fileLocations; +@property (nonatomic, copy) NSString *userData; + +- (void)appendTag:(NSString *)tag; +- (void)logVerbose:(NSString *)log; +- (void)logDebug:(NSString *)log; +- (void)logInfo:(NSString *)log; +- (void)logWarn:(NSString *)log; +- (void)logError:(NSString *)log; +- (void)appendToConsoleLogs:(NSString *)log; +- (void)setUserAttribute:(NSString *)userAttribute withKey:(NSString *)key; +- (void)addFileAttachmentWithURL:(NSURL *)url; +- (void)addFileAttachmentWithData:(NSData *)data; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGSurvey.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGSurvey.h new file mode 100644 index 0000000..3142a59 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGSurvey.h @@ -0,0 +1,17 @@ +// +// IBGSurvey.h +// InstabugSurveys +// +// Created by Yousef Hamza on 5/25/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import + +@interface IBGSurvey : NSObject + +@property (nonatomic, readonly) NSString *title; + +- (void)show; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGSurveys.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGSurveys.h new file mode 100644 index 0000000..d5f6d41 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGSurveys.h @@ -0,0 +1,96 @@ +// +// IBGSurveys.h +// Instabug +// +// Created by Yousef Hamza on 5/17/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import +#import "IBGSurvey.h" + +NS_SWIFT_NAME(Surveys) +@interface IBGSurveys : NSObject + +@property (class, atomic, assign) BOOL enabled; +/** + @brief Sets whether auto surveys showing are enabled or not. + + @discussion If you disable surveys auto showing on the SDK but still have active surveys on your Instabug dashboard, those surveys are still going to be sent to the device, but are not going to be shown automatically. + + To manually display any available surveys, call `+ [Instabug showSurveyIfAvailable]`. + + Defaults to YES. + */ +@property (class, atomic, assign) BOOL autoShowingEnabled; + +/** + @brief Returns array of available surveys that match the current device/user. + */ +@property (class, atomic, readonly, strong) NSArray *availableSurveys; + +/** + @brief Sets a block of code to be executed just before the survey's UI is presented. + + @discussion This block is executed on the UI thread. Could be used for performing any UI changes before the survey's UI + is shown. + */ +@property (class, atomic, strong) void(^willShowSurveyHandler)(void); + +/** + @brief Sets a block of code to be executed right after the survey's UI is dismissed. + + @discussion This block is executed on the UI thread. Could be used for performing any UI changes after the survey's UI + is dismissed. + */ +@property (class, atomic, strong) void(^didDismissSurveyHandler)(void); + +/** + @brief Setting an option for all the surveys to show a welcome screen before the user starts taking the survey. + + @discussion By enabling this option, any survey that appears to the user will have a welcome screen with a title, subtitle + and a button that if clicked, will take the user to the survey. All the strings in the welcome screen have a default value + and localized. They can also be modified using the strings API. The default value of this option is false. + */ +@property (class, atomic, assign) BOOL shouldShowWelcomeScreen; + +/** + @brief Shows one of the surveys that were not shown before, that also have conditions that match the current device/user. + + @discussion Does nothing if there are no available surveys. + */ ++ (void)showSurveyIfAvailable; + +/** + @brief Shows Survey with a specific token. + + @discussion Does nothing if there are no available surveys with that specific token. Answered and canceled surveys won't show up again. + + @param surveyToken A String with a survey token. + */ ++ (void)showSurveyWithToken:(NSString *)surveyToken; + + +/** + @brief Sets a threshold for numbers of sessions and another for number of days required before a survey, that has been dismissed once, would show again. + + @discussion When a survey that has been shown to the user gets dismissed once, it will not reappear to the user unless a certain number of sessions have started AND a certain number of days have passed since the user first dismissed the survey. Note that if a survey is dismissed for a second time, it will not show again, in other words, it will be set to `canceled`. This applies to both surveys with and without tokens. + + Please note that this overrides the dashboard configuration for reshowing if called. + + @param sessionCount : Number of sessions required to be initialized before a dismissed survey can be shown again. + @param daysCount : Number of days required to pass before a dismissed survey can be shown again. + */ ++ (void)setThresholdForReshowingSurveyAfterDismiss:(NSInteger)sessionCount daysCount:(NSInteger)daysCount DEPRECATED_MSG_ATTRIBUTE("Reshowing the survey can now be controlled from the dashboard for any new survey you create."); + +/** + @brief Returns true if the survey with a specific token was answered before . + + @discussion Will return false if the token does not exist or if the survey was not answered before. + + @param surveyToken A String with a survey token. + */ ++ (BOOL)hasRespondedToSurveyWithToken:(NSString *)surveyToken; + + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGTypes.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGTypes.h new file mode 100644 index 0000000..a2200c3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/IBGTypes.h @@ -0,0 +1,387 @@ +/* + File: InstabugCore/IBGTypes.h + + Contains: Enums and Constants for using Instabug's SDK. + + Copyright: (c) 2013-2018 by Instabug, Inc., all rights reserved. + + Version: 0.0.0 + */ + +#import + +#define IBG_DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide for instructions on migrating to SDK v8.1 APIs.") + +/// ------------------------------ +/// @name User-facing Strings Keys +/// ------------------------------ + +// Predefined keys to be used to override any of the user-facing strings in the SDK. See + [Instabug setValue:forStringWithKey] + +extern NSString * const kIBGStartAlertTextStringName; +extern NSString * const kIBGShakeStartAlertTextStringName; +extern NSString * const kIBGTwoFingerSwipeStartAlertTextStringName; +extern NSString * const kIBGEdgeSwipeStartAlertTextStringName; +extern NSString * const kIBGScreenshotStartAlertTextStringName; +extern NSString * const kIBGFloatingButtonStartAlertTextStringName; +extern NSString * const kIBGBetaWelcomeMessageWelcomeStepTitle; +extern NSString * const kIBGBetaWelcomeMessageWelcomeStepContent; +extern NSString * const kIBGBetaWelcomeMessageHowToReportStepTitle; +extern NSString * const kIBGBetaWelcomeMessageHowToReportStepContent; +extern NSString * const kIBGBetaWelcomeMessageFinishStepTitle; +extern NSString * const kIBGBetaWelcomeMessageFinishStepContent; +extern NSString * const kIBGBetaWelcomeDoneButtonTitle; +extern NSString * const kIBGLiveWelcomeMessageTitle; +extern NSString * const kIBGLiveWelcomeMessageContent; +extern NSString * const kIBGInvalidEmailMessageStringName; +extern NSString * const kIBGInvalidEmailTitleStringName; +extern NSString * const kIBGInvalidCommentMessageStringName; +extern NSString * const kIBGInvalidCommentTitleStringName; +extern NSString * const kIBGInvocationTitleStringName; +extern NSString * const kIBGTalkToUsStringName DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-setvalue-string-forstringwithkey-kibgtalktousstringname for instructions on migrating to SDK v8.1 APIs."); +extern NSString * const kIBGFeatureRequetsPromptName; +extern NSString * const kIBGAskAQuestionStringName; +extern NSString * const kIBGReportBugStringName; +extern NSString * const kIBGReportFeedbackStringName; +extern NSString * const kIBGPhotoPickerTitle; +extern NSString * const kIBGProgressViewTitle; +extern NSString * const kIBGGalleryPermissionDeniedAlertTitle; +extern NSString * const kIBGGalleryPermissionDeniedAlertMessage; +extern NSString * const kIBGMaximumSizeExceededAlertTitle; +extern NSString * const kIBGMaximumSizeExceededAlertMessage; +extern NSString * const kIBGiCloudImportErrorAlertTitle; +extern NSString * const kIBGiCloudImportErrorAlertMessage; +extern NSString * const kIBGEmailFieldPlaceholderStringName; +extern NSString * const kIBGCommentFieldPlaceholderForBugReportStringName; +extern NSString * const kIBGCommentFieldPlaceholderForFeedbackStringName; +extern NSString * const kIBGChatReplyFieldPlaceholderStringName; +extern NSString * const kIBGAddScreenRecordingMessageStringName; +extern NSString * const kIBGAddVoiceMessageStringName; +extern NSString * const kIBGAddImageFromGalleryStringName; +extern NSString * const kIBGAddExtraScreenshotStringName; +extern NSString * const kIBGAudioRecordingPermissionDeniedTitleStringName; +extern NSString * const kIBGAudioRecordingPermissionDeniedMessageStringName; +extern NSString * const kIBGScreenRecordingPermissionDeniedMessageStringName; +extern NSString * const kIBGMicrophonePermissionAlertSettingsButtonTitleStringName; +extern NSString * const kIBGMicrophonePermissionAlertLaterButtonTitleStringName; +extern NSString * const kIBGChatsTitleStringName; +extern NSString * const kIBGTeamStringName; +extern NSString * const kIBGRecordingMessageToHoldTextStringName; +extern NSString * const kIBGRecordingMessageToReleaseTextStringName; +extern NSString * const kIBGMessagesNotificationTitleSingleMessageStringName; +extern NSString * const kIBGMessagesNotificationTitleMultipleMessagesStringName; +extern NSString * const kIBGScreenshotTitleStringName; +extern NSString * const kIBGOkButtonTitleStringName; +extern NSString * const kIBGSendButtonTitleStringName; +extern NSString * const kIBGCancelButtonTitleStringName; +extern NSString * const kIBGThankYouAlertTitleStringName; +extern NSString * const kIBGThankYouAlertMessageStringName; +extern NSString * const kIBGAudioStringName; +extern NSString * const kIBGScreenRecordingStringName; +extern NSString * const kIBGImageStringName; +extern NSString * const kIBGReachedMaximimNumberOfAttachmentsTitleStringName; +extern NSString * const kIBGReachedMaximimNumberOfAttachmentsMessageStringName; +extern NSString * const kIBGVideoRecordingFailureMessageStringName; +extern NSString * const kIBGSurveyEnterYourAnswerTextPlaceholder; +extern NSString * const kIBGSurveyNoAnswerTitle; +extern NSString * const kIBGSurveyNoAnswerMessage; +extern NSString * const kIBGVideoPressRecordTitle; +extern NSString * const kIBGCollectingDataText; +extern NSString * const kIBGLowDiskStorageTitle; +extern NSString * const kIBGLowDiskStorageMessage; +extern NSString * const kIBGInboundByLineMessage; +extern NSString * const kIBGExtraFieldIsRequiredText; +extern NSString * const kIBGExtraFieldMissingDataText; +extern NSString * const kIBGFeatureRequestsTitle; +extern NSString * const kIBGFeatureDetailsTitle; +extern NSString * const kIBGStringFeatureRequestsRefreshText; +extern NSString * const kIBGFeatureRequestErrorStateTitleLabel; +extern NSString * const kIBGFeatureRequestErrorStateDescriptionLabel; +extern NSString * const kIBGFeatureRequestSortingByRecentlyUpdatedText; +extern NSString * const kIBGFeatureRequestSortingByTopVotesText; +extern NSString * const kIBGStringFeatureRequestAllFeaturesText; +extern NSString * const kIBGAddNewFeatureRequestText; +extern NSString * const kIBGAddNewFeatureRequestToastText; +extern NSString * const kIBGAddNewFeatureRequestErrorToastText; +extern NSString * const kIBGAddNewFeatureRequestLoadingHUDTitle; +extern NSString * const kIBGAddNewFeatureRequestSuccessHUDTitle; +extern NSString * const kIBGAddNewFeatureRequestSuccessHUDMessage; +extern NSString * const kIBGAddNewFeatureRequestTryAgainText; +extern NSString * const kIBGAddNewFeatureRequestCancelPromptTitle; +extern NSString * const kIBGAddNewFeatureRequestCancelPromptYesAction; +extern NSString * const kIBGFeatureRequestInvalidEmailText; +extern NSString * const kIBGFeatureRequestTimelineEmptyText; +extern NSString * const kIBGFeatureRequestTimelineErrorDescriptionLabel; +extern NSString * const kIBGFeatureRequestStatusChangeText; +extern NSString * const kIBGFeatureRequestAddButtonText; +extern NSString * const kIBGFeatureRequestVoteWithCountText; +extern NSString * const kIBGFeatureRequestVoteText; +extern NSString * const kIBGFeatureRequestPostButtonText; +extern NSString * const kIBGFeatureRequestCommentsText; +extern NSString * const kIBGFeatureRequestAuthorText; +extern NSString * const kIBGFeatureRequestEmptyViewTitle; +extern NSString * const kIBGFeatureRequestAddYourIdeaText; +extern NSString * const kIBGFeatureRequestAnonymousText; +extern NSString * const kIBGFeatureRequestStatusPosted; +extern NSString * const kIBGFeatureRequestStatusPlanned; +extern NSString * const kIBGFeatureRequestStatusStarted; +extern NSString * const kIBGFeatureRequestStatusCompleted; +extern NSString * const kIBGFeatureRequestStatusMaybeLater; +extern NSString * const kIBGFeatureRequestStatusMoreText; +extern NSString * const kIBGFeatureRequestStatusLessText; +extern NSString * const kIBGFeatureRequestAddYourThoughtsText; +extern NSString * const kIBGEmailRequiredText; +extern NSString * const kIBGNameText; +extern NSString * const kIBGEmailText; +extern NSString * const kIBGTitleText; +extern NSString * const kIBGDescriptionText; +extern NSString * const kIBGStringFeatureRequestMyFeaturesText; +extern NSString * const kIBGSurveyIntroTitleText; +extern NSString * const kIBGSurveyIntroDescriptionText; +extern NSString * const kIBGSurveyIntroTakeSurveyButtonText; +extern NSString * const kIBGSurveyIntroDismissButtonText; +extern NSString * const kIBGSurveyThankYouTitleText DEPRECATED_MSG_ATTRIBUTE("kIBGSurveyThankYouTitleText is deprecated. You can edit this string from the dashboard, and use kIBGCustomSurveyThankYouTitleText for Custom surveys."); +extern NSString * const kIBGSurveyThankYouDescriptionText DEPRECATED_MSG_ATTRIBUTE("kIBGSurveyThankYouDescriptionText is deprecated. You can edit this string from the dashboard, and use kIBGCustomSurveyThankYouDescriptionText for Custom surveys."); +extern NSString * const kIBGStoreRatingThankYouTitleText; +extern NSString * const kIBGStoreRatingThankYouDescriptionText; +extern NSString * const kIBGCustomSurveyThankYouTitleText; +extern NSString * const kIBGCustomSurveyThankYouDescriptionText; +extern NSString * const kIBGSurveysNPSLeastLikelyStringName; +extern NSString * const kIBGSurveysNPSMostLikelyStringName; +extern NSString * const kIBGSurveyNextButtonTitle; +extern NSString * const kIBGSurveySubmitButtonTitle; +extern NSString * const kIBGSurveyAppStoreThankYouTitle; +extern NSString * const kIBGSurveyAppStoreButtonTitle; +extern NSString * const kIBGExpectedResultsStringName; +extern NSString * const kIBGActualResultsStringName; +extern NSString * const kIBGStepsToReproduceStringName; +extern NSString * const kIBGReplyButtonTitleStringName; +extern NSString * const kIBGAddAttachmentButtonTitleStringName; +extern NSString * const kIBGDiscardAlertTitle; +extern NSString * const kIBGDiscardAlertMessage; +extern NSString * const kIBGDiscardAlertAction; +extern NSString * const kIBGDiscardAlertCancel; +extern NSString * const kIBGVideoGalleryErrorMessageStringName; +extern NSString * const kIBGVideoDurationErrorTitle; +extern NSString * const kIBGVideoDurationErrorMessage; +extern NSString * const kIBGAutoScreenRecordingAlertAllowText; +extern NSString * const kIBGAutoScreenRecordingAlertAlwaysAllowText; +extern NSString * const kIBGAutoScreenRecordingAlertDenyText; +extern NSString * const kIBGAutoScreenRecordingAlertTitleText; +extern NSString * const kIBGAutoScreenRecordingAlertBodyText; + +/// ----------- +/// @name Enums +/// ----------- + +/** + The event used to invoke the feedback form. + */ +typedef NS_OPTIONS(NSInteger, IBGInvocationEvent) { + /** Shaking the device while in any screen to show the feedback form. */ + IBGInvocationEventShake = 1 << 0, + /** Taking a screenshot using the Home+Lock buttons while in any screen to show the feedback form. */ + IBGInvocationEventScreenshot = 1 << 1, + /** Swiping two fingers left while in any screen to show the feedback form. */ + IBGInvocationEventTwoFingersSwipeLeft = 1 << 2, + /** Swiping one finger left from the right edge of the screen to show the feedback form, substituted with IBGInvocationEventTwoFingersSwipeLeft on iOS 6.1.3 and earlier. */ + IBGInvocationEventRightEdgePan = 1 << 3, + /** Shows a floating button on top of all views, when pressed it takes a screenshot. */ + IBGInvocationEventFloatingButton = 1 << 4, + /** No event will be registered to show the feedback form, you'll need to code your own and call the method showFeedbackForm. */ + IBGInvocationEventNone = 1 << 5, +}; + +/** + The color theme of the different UI elements. + */ +typedef NS_ENUM(NSInteger, IBGColorTheme) { + IBGColorThemeLight, + IBGColorThemeDark +}; + +/** + The mode used upon invocating the SDK. + */ +typedef NS_ENUM(NSInteger, IBGInvocationMode) { + IBGInvocationModeNA, + IBGInvocationModeNewBug, + IBGInvocationModeNewFeedback, + IBGInvocationModeNewChat, + IBGInvocationModeChatsList +}; + +/** + Deprecated, should use IBGBugReportingOption instead. + */ +__attribute__((deprecated)) +typedef NS_OPTIONS(NSInteger, IBGBugReportingInvocationOption) { + IBGBugReportingInvocationOptionEmailFieldHidden = 1 << 0, + IBGBugReportingInvocationOptionEmailFieldOptional = 1 << 1, + IBGBugReportingInvocationOptionCommentFieldRequired = 1 << 2, + IBGBugReportingInvocationOptionDisablePostSendingDialog = 1 << 3, + IBGBugReportingInvocationOptionNone = 1 << 4, +}; + +/** + Type of report to be submitted. + */ +typedef NS_OPTIONS(NSInteger, IBGBugReportingReportType) { + IBGBugReportingReportTypeBug = 1 << 0, + IBGBugReportingReportTypeFeedback = 1 << 1, +}; + + +typedef NS_OPTIONS(NSInteger, IBGBugReportingOption) { + IBGBugReportingOptionEmailFieldHidden = 1 << 0, + IBGBugReportingOptionEmailFieldOptional = 1 << 1, + IBGBugReportingOptionCommentFieldRequired = 1 << 2, + IBGBugReportingOptionDisablePostSendingDialog = 1 << 3, + IBGBugReportingOptionNone = 1 << 4, +}; + +typedef NS_ENUM(NSInteger, IBGReportType) { + IBGReportTypeBug, + IBGReportTypeFeedback +}; + +/** + Type of SDK dismiss. + */ +typedef NS_ENUM(NSInteger, IBGDismissType) { + /** Dismissed after report submit */ + IBGDismissTypeSubmit, + /** Dismissed via cancel */ + IBGDismissTypeCancel, + /** Dismissed while taking screenshot */ + IBGDismissTypeAddAttachment +}; + +/** + Supported locales. + */ +typedef NS_ENUM(NSInteger, IBGLocale) { + IBGLocaleArabic, + IBGLocaleChineseSimplified, + IBGLocaleChineseTaiwan, + IBGLocaleChineseTraditional, + IBGLocaleCzech, + IBGLocaleDanish, + IBGLocaleDutch, + IBGLocaleEnglish, + IBGLocaleFrench, + IBGLocaleGerman, + IBGLocaleItalian, + IBGLocaleJapanese, + IBGLocaleKorean, + IBGLocaleNorwegian, + IBGLocalePolish, + IBGLocalePortugese, + IBGLocalePortugueseBrazil, + IBGLocaleRussian, + IBGLocaleSlovak, + IBGLocaleSpanish, + IBGLocaleSwedish, + IBGLocaleTurkish, + IBGLocaleHungarian +}; + +/** + Verbosity level of the SDK debug logs. This has nothing to do with IBGLog, and only affect the logs used to debug the + SDK itself. + + Defaults to IBGSDKDebugLogsLevelError. Make sure you only use IBGSDKDebugLogsLevelError or IBGSDKDebugLogsLevelNone in + production builds. + */ +typedef NS_ENUM(NSInteger, IBGSDKDebugLogsLevel) { + IBGSDKDebugLogsLevelVerbose, + IBGSDKDebugLogsLevelDebug, + IBGSDKDebugLogsLevelError, + IBGSDKDebugLogsLevelNone +}; + +/** + The prompt option selected in Instabug prompt. + */ +typedef NS_OPTIONS(NSInteger, IBGPromptOption) { + IBGPromptOptionChat = 1 << 0, + IBGPromptOptionBug = 1 << 1, + IBGPromptOptionFeedback = 1 << 2, + IBGPromptOptionNone = 1 << 3, +}; + +/** + Instabug floating buttons positions. + */ +typedef NS_ENUM(NSInteger, IBGPosition) { + IBGPositionBottomRight, + IBGPositionTopRight, + IBGPositionBottomLeft, + IBGPositionTopLeft +}; + +/** + The Conosle Log Level. + */ +typedef NS_ENUM(NSInteger, IBGLogLevel) { + IBGLogLevelDefault, + IBGLogLevelTrace, + IBGLogLevelInfo, + IBGLogLevelWarning, + IBGLogLevelError, + IBGLogLevelFatal +}; + +/** + The user steps option. + */ +typedef NS_ENUM(NSInteger, IBGUserStepsMode) { + IBGUserStepsModeEnabledWithNoScreenshots, + IBGUserStepsModeDisable +}; + + /** + The attachment types selected in Attachment action sheet. + */ +typedef NS_OPTIONS(NSInteger, IBGAttachmentType) { + IBGAttachmentTypeScreenShot = 1 << 1, + IBGAttachmentTypeExtraScreenShot = 1 << 2, + IBGAttachmentTypeGalleryImage = 1 << 4, + IBGAttachmentTypeScreenRecording = 1 << 6, +}; + +/** + The extended bug report mode. + */ +typedef NS_ENUM(NSInteger, IBGExtendedBugReportMode) { + IBGExtendedBugReportModeEnabledWithRequiredFields, + IBGExtendedBugReportModeEnabledWithOptionalFields, + IBGExtendedBugReportModeDisabled +}; + +typedef NS_OPTIONS(NSInteger, IBGAction) { + IBGActionAllActions = 1 << 0, + IBGActionReportBug = 1 << 1, + IBGActionRequestNewFeature = 1 << 2, + IBGActionAddCommentToFeature = 1 << 3, +}; + +/** + The welcome message mode. + */ +typedef NS_ENUM(NSInteger, IBGWelcomeMessageMode) { + IBGWelcomeMessageModeLive, + IBGWelcomeMessageModeBeta, + IBGWelcomeMessageModeDisabled +}; + +/* CHECK NULLABILITY! */ +typedef void (^NetworkObfuscationCompletionBlock)(NSData *data, NSURLResponse *response); + +/* Platform */ +typedef NS_ENUM(NSInteger, IBGPlatform) { + IBGPlatformIOS, + IBGPlatformReactNative, + IBGPlatformCordova, + IBGPlatformXamarin +}; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/Instabug.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/Instabug.h new file mode 100644 index 0000000..ae9e4b8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/Instabug.h @@ -0,0 +1,348 @@ +/* + File: Instabug/Instabug.h + + Contains: API for using Instabug's SDK. + + Copyright: (c) 2013-2018 by Instabug, Inc., all rights reserved. + + Version: 8.0.8 + */ + +#import +#import +#import "InstabugCore.h" +#import "IBGNetworkLogger.h" +#import "IBGReport.h" +#import "IBGLog.h" +#import "IBGBugReporting.h" +#import "IBGCrashReporting.h" +#import "IBGSurveys.h" +#import "IBGFeatureRequests.h" +#import "IBGChats.h" +#import "IBGReplies.h" +#import "UIView+Instabug.h" + +/** + This is the API for using Instabug's SDK. For more details about the SDK integration, + please visit https://docs.instabug.com/docs/ios-integration + */ + +NS_ASSUME_NONNULL_BEGIN + +@interface Instabug : NSObject + +/** + @brief Sets whether the session profiler is enabled or disabled. + + @discussion The session profiler is enabled by default and it attaches to the bug and crash reports the following information during the last 60 seconds before the report is sent. + 1. CPU load. + 2. Dispatch queues latency. + 3. Memory usage. + 4. Storage usage. + 5. Connectivity. + 6. Battery percentage and state. + 7. Orientation. + */ +@property (class, atomic, assign) BOOL sessionProfilerEnabled; + +/** + @brief Sets maximum auto screen recording video duration. + + @discussion sets maximum auto screen recording video duration with max value 30 seconds and min value greater than 1 sec. + */ +@property (class, atomic, assign) CGFloat autoScreenRecordingDuration DEPRECATED_MSG_ATTRIBUTE("'autoScreenRecordingDuration' is deprecated: first deprecated in SDK 8.2.3 - autoScreenRecordingDuration is deprecated. Use IBGBugReporting.autoScreenRecordingDuration instead."); + +/** + @brief Enables/disables inspect view hierarchy when reporting a bug/feedback. + */ +@property (class, atomic, assign) BOOL shouldCaptureViewHierarchy DEPRECATED_MSG_ATTRIBUTE("'shouldCaptureViewHierarchy' is deprecated: first deprecated in SDK 8.2.3 - shouldCaptureViewHierarchy is deprecated. Use IBGBugReporting.shouldCaptureViewHierarchy instead."); + +/** + @brief Sets the primary color of the SDK's UI. + + @discussion Sets the color of UI elements indicating interactivity or call to action. + */ +@property (class, atomic, strong) UIColor *tintColor; + +/** + @brief Sets a block of code to be executed before sending each report. + + @discussion This block is executed in the background before sending each report. Could be used for attaching logs + and extra data to reports. + + @param willSendReportHandler A block of code that gets executed before sending each bug report. + */ +@property(class, atomic, strong) IBGReport*(^willSendReportHandler)(IBGReport *report); + +/** + @brief Sets whether the SDK is tracking user steps or not. + + @discussion Enabling user steps would give you an insight on the scenario a user has performed before encountering a + bug or a crash. User steps are attached with each report being sent. + + User Steps tracking is enabled by default if it's available in your current plan. + */ +@property (class, atomic, assign) BOOL trackUserSteps; + +/** + @brief Sets whether user steps tracking is visual, non visual or disabled. + + @discussion Enabling user steps would give you an insight on the scenario a user has performed before encountering a + bug or a crash. User steps are attached with each report being sent. + + User Steps tracking is enabled by default if it's available in your current plan. + */ +@property (class, atomic, assign) IBGUserStepsMode reproStepsMode; + + +/** + @brief Sets the welcome message mode to live, beta or disabled. + + @discussion By default, the welcome message live mode is enabled. It appears automatically after 10 seconds from the user's first session. You can change it to the beta mode or disable it. + The live mode consists of one step to inform the users how to report a bug or feedback. The beta mode consists of three steps to welcome your testers on board, inform them how to report a bug or feedback and to motivate them to always be on the latest app version. Please note, the into message appears only if the invocation event isn't set to none. + */ +@property (class, atomic, assign) IBGWelcomeMessageMode welcomeMessageMode; + +/** + @brief Attaches user data to each report being sent. + + @discussion Each call to this method overrides the user data to be attached. + Maximum size of the string is 1,000 characters. + */ +@property (class, atomic, strong) NSString *userData; + + +/** + @brief Starts the SDK. + + @discussion This is the main SDK method that does all the magic. This is the only method that SHOULD be called. + Should be called at the end of `-[UIApplicationDelegate application:didFinishLaunchingWithOptions:]`. + + @param token The token that identifies the app, you can find it on your dashboard. + @param invocationEvents One or more event that invokes the SDK's UI. + + @see IBGInvocationEvent + */ ++ (void)startWithToken:(NSString *)token invocationEvents:(IBGInvocationEvent)invocationEvents; + +/** + @brief Shows Instabug Prompt Options. + + @discussion By default, it contains Report a problem, Suggest an improvement, Ask a question, and a button that navigates to the chats list. To control which options should be enabled, see IBGBugReporting.enabled, IBGChats.enabled, and IBGReplies.enabled. + */ ++ (void)show; + +/** + @brief Add file to attached files with each report being sent. + + @discussion A new copy of the file at fileURL will be attached with each bug report being sent. The file is only copied + at the time of sending the report, so you could safely call this API whenever the file is available on disk, and the copy + attached to your bug reports will always contain that latest changes at the time of sending the report. + + Each call to this method adds the file to the files attached, until a maximum of 3 then it overrides the first file. + The file has to be available locally at the provided path when the report is being sent. + + @param fileURL Path to a file that's going to be attached to each report. + */ ++ (void)addFileAttachmentWithURL:(NSURL *)fileURL; + + +/** + @brief Add a set of data as a file attachment to be sent with each report. + + @discussion The data will be written to a file and will be attached with each report. + + Each call to this method adds this set of data as a file attachment, until a maximum of 3 then it overrides the first data. + + @param data NSData to be added as a file attachment with each report. + */ ++(void)addFileAttachmentWithData:(NSData *)data; + +/** + @brief Clear list of files to be attached with each report. + + @discussion This method doesn't delete any files from the file system. It will just removes them for the list of files + to be attached with each report. + */ ++ (void)clearFileAttachments; + +/** + @brief Shows the welcome message in a specific mode. + + @discussion By default, the welcome message live mode is enabled. It appears automatically after 10 seconds from the user's first session. You can show it manually in a specific mode through this API. + The live mode consists of one step to inform the users how to report a bug or feedback. The beta mode consists of three steps to welcome your testers on board, inform them how to report a bug or feedback and to motivate them to always be on the latest app version. Please note, the into message appears only if the invocation event isn't set to none. + + @param welcomeMessageMode An enum to set the welcome message mode to live, beta or disabled. + */ ++ (void)showWelcomeMessageWithMode:(IBGWelcomeMessageMode)welcomeMessageMode; + + +/** + @brief Sets the user email and name for all sent reports. + + @param email Email address to be set as the user's email. + @param name Name of the user to be set. + */ ++ (void)identifyUserWithEmail:(NSString *)email name:(nullable NSString *)name; + +/** + @brief Resets the value of the user's email and name, previously set using `+ [Instabug identifyUserWithEmail:name:]`. + + @discussion This method also resets all chats currently on the device and removes any set user attributes. + */ ++ (void)logOut; + +/** + @brief Sets the SDK's locale. + + @discussion Use to change the SDK's UI to different language. + Defaults to the device's current locale. + + @param locale A locale to set the SDK to. + + @see IBGLocale + */ ++ (void)setLocale:(IBGLocale)locale; + +/** + @brief Sets the color theme of the SDK's whole UI. + + @param colorTheme An `IBGColorTheme` to set the SDK's UI to. + + @see IBGColorTheme + */ ++ (void)setColorTheme:(IBGColorTheme)colorTheme; + +/** + @brief Sets a block of code that is used to capture a screenshot. + + @discussion Should only be used if your app uses OpenGL. + + @param screenshotCapturingHandler A block of code that's going to be used to capture screenshots. + */ ++ (void)setScreenshotCapturingHandler:(UIImage *(^)(void))screenshotCapturingHandler; + +/** + @brief Appends a set of tags to previously added tags of reported feedback, bug or crash. + + @param tags An array of tags to append to current tags. +*/ ++ (void)appendTags:(NSArray *)tags; + +/** + @brief Manually removes all tags of reported feedback, bug or crash. + */ ++ (void)resetTags; + +/** + @brief Gets all tags of reported feedback, bug or crash. + + @return An array of tags. + */ ++ (NSArray *)getTags; + +/** + @brief Overrides any of the strings shown in the SDK with custom ones. + + @discussion Allows you to customize any of the strings shown to users in the SDK. + + @param value String value to override the default one. + @param key Key of string to override. Use predefined keys like IBGShakeStartAlertTextStringName, + IBGEmailFieldPlaceholderStringName, etc. + + @see IBGTypes + */ ++ (void)setValue:(NSString *)value forStringWithKey:(NSString *)key; + +/** + @brief Set custom user attributes that are going to be sent with each feedback, bug or crash. + + @param value User attribute value. + @param key User attribute key. + */ ++ (void)setUserAttribute:(NSString *)value withKey:(NSString *)key; + +/** + @brief Returns the user attribute associated with a given key. + + @param key The key for which to return the corresponding value.. + + @return The value associated with aKey, or nil if no value is associated with aKey. + */ ++ (nullable NSString *)userAttributeForKey:(NSString *)key; + +/** + @brief Removes a given key and its associated value from user attributes. + + Does nothing if aKey does not exist. + + @param key The key to remove. + */ ++ (void)removeUserAttributeForKey:(NSString *)key; + +/** + @brief Returns all user attributes. + + @return A new dictionary containing all the currently set user attributes, or an empty dictionary if no user attributes have been set. + */ ++ (nullable NSDictionary *)userAttributes; + +/// ------------------- +/// @name SDK Reporting +/// ------------------- + +/** + @brief Logs a user event that happens through the lifecycle of the application. + + @discussion Logged user events are going to be sent with each report, as well as at the end of a session. + + @param name Event name. + */ ++ (void)logUserEventWithName:(NSString *)name; + +#pragma mark - SDK Debugging + +/// ------------------------ +/// @name SDK Debugging +/// ------------------------ + +/** + @brief Sets the verbosity level of logs used to debug the Instabug SDK itself. + + @discussion This API sets the verbosity level of logs used to debug The SDK. The defualt value in debug mode is IBGSDKDebugLogsLevelVerbose and in production is IBGSDKDebugLogsLevelError. + */ +@property (class, atomic, assign) IBGSDKDebugLogsLevel sdkDebugLogsLevel; + +/* + +------------------------------------------------------------------------+ + | Deprecated APIs | + +------------------------------------------------------------------------+ + | The following section includes all deprecated APIs. | + | | + | We've made a few changes to our APIs starting from version 8.1 to make | + | them more intuitive and easily reachable. | + | | + | While the APIs below still function, they will be completely removed | + | in a future release. | + | | + | To adopt the new changes, please refer to our migration guide at: | + | https://docs.instabug.com/docs/ios-migration-guide | + +------------------------------------------------------------------------+ + */ + ++ (void)setPushNotificationsEnabled:(BOOL)isPushNotificationsEnabled DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-setpushnotificationsenabled for instructions on migrating to SDK v8.1 APIs."); + ++ (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-didreceiveremotenotification for instructions on migrating to SDK v8.1 APIs."); + ++ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-didregisterforremotenotificationswithdevicetoken for instructions on migrating to SDK v8.1 APIs."); + +@property (class, atomic, strong) void (^didRecieveReplyHandler)(void) DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-didrecievereplyhandler for instructions on migrating to SDK v8.1 APIs."); + +@property (class, atomic, assign) BOOL replyNotificationsEnabled DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-replynotificationsenabled for instructions on migrating to SDK v8.1 APIs."); + +@property (class, atomic, assign, readonly) NSInteger unreadMessagesCount DEPRECATED_MSG_ATTRIBUTE("See https://docs.instabug.com/docs/ios-sdk-8-1-migration-guide#section-unreadmessagescount for instructions on migrating to SDK v8.1 APIs."); + +@end + + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/InstabugCore.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/InstabugCore.h new file mode 100644 index 0000000..2eec436 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/InstabugCore.h @@ -0,0 +1,17 @@ +/* + File: InstabugCore/InstabugCore.h + + Contains: Enums and Constants for using Instabug's SDK. + + Copyright: (c) 2013-2018 by Instabug, Inc., all rights reserved. + + Version: 0.0.0 + */ + +#import +#import "IBGTypes.h" +#import "IBGReport.h" + +@interface InstabugCore : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/UIView+Instabug.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/UIView+Instabug.h new file mode 100644 index 0000000..0097e0c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Headers/UIView+Instabug.h @@ -0,0 +1,19 @@ +// +// UIView+Instabug.h +// InstabugUtilities +// +// Created by Aly Yakan on 7/17/18. +// Copyright © 2018 Moataz. All rights reserved. +// + +#import + +@interface UIView (Instabug) + +/** + @brief Set this to true on any UIView to mark it as private. + Doing this will exclude it from all screenshots, view hierarchy captures and screen recordings. + */ +@property (nonatomic, assign) BOOL instabug_privateView; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Info.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Info.plist new file mode 100644 index 0000000..aa14087 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Info.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Instabug b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Instabug new file mode 100755 index 0000000..aa4b9b0 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Instabug differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Assets.car b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Assets.car new file mode 100644 index 0000000..bf72f9e Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Assets.car differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Config.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Config.plist new file mode 100644 index 0000000..3967e06 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Config.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetCell.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetCell.nib new file mode 100644 index 0000000..c16b673 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetCell.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/objects-11.0+.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/objects-11.0+.nib new file mode 100644 index 0000000..2a0e655 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/objects-11.0+.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/runtime.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/runtime.nib new file mode 100644 index 0000000..7a7a1a4 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/runtime.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGBugVC-iPhone.nib/objects-11.0+.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGBugVC-iPhone.nib/objects-11.0+.nib new file mode 100644 index 0000000..cad172b Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGBugVC-iPhone.nib/objects-11.0+.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGBugVC-iPhone.nib/runtime.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGBugVC-iPhone.nib/runtime.nib new file mode 100644 index 0000000..70a7cc7 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGBugVC-iPhone.nib/runtime.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatCell.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatCell.nib new file mode 100644 index 0000000..0da855e Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatCell.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatListVC-iPhone.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatListVC-iPhone.nib new file mode 100644 index 0000000..c73d139 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatListVC-iPhone.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatVC-iPhone.nib/objects-11.0+.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatVC-iPhone.nib/objects-11.0+.nib new file mode 100644 index 0000000..b60eda3 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatVC-iPhone.nib/objects-11.0+.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatVC-iPhone.nib/runtime.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatVC-iPhone.nib/runtime.nib new file mode 100644 index 0000000..0703cd6 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGChatVC-iPhone.nib/runtime.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGFullScreenImageViewController.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGFullScreenImageViewController.nib new file mode 100644 index 0000000..ce776a9 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGFullScreenImageViewController.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPoweredByView.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPoweredByView.nib new file mode 100644 index 0000000..6389629 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPoweredByView.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPromptCell.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPromptCell.nib new file mode 100644 index 0000000..b4e5d9d Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPromptCell.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPromptVC-iPhone.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPromptVC-iPhone.nib new file mode 100644 index 0000000..387b697 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGPromptVC-iPhone.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGReplyView-iPhone.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGReplyView-iPhone.nib new file mode 100644 index 0000000..69056b6 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGReplyView-iPhone.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGReportCategoriesVC-iPhone.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGReportCategoriesVC-iPhone.nib new file mode 100644 index 0000000..50e4821 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGReportCategoriesVC-iPhone.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGScreenshotVC-iPhone.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGScreenshotVC-iPhone.nib new file mode 100644 index 0000000..532c1fe Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGScreenshotVC-iPhone.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGVideoPlaybackViewController.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGVideoPlaybackViewController.nib new file mode 100644 index 0000000..3842161 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGVideoPlaybackViewController.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGVoiceNoteRecordingViewController-iPhone.nib b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGVoiceNoteRecordingViewController-iPhone.nib new file mode 100644 index 0000000..733086b Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/IBGVoiceNoteRecordingViewController-iPhone.nib differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Info.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Info.plist new file mode 100644 index 0000000..11ee3a0 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Info.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Inject_DSYM_Project-Archive.sh b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Inject_DSYM_Project-Archive.sh new file mode 100644 index 0000000..094b820 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Inject_DSYM_Project-Archive.sh @@ -0,0 +1,25 @@ +echo "Instabug: Started inject dSYM and bcsymbolmap inside project archive." + +Instabug_DSYM_PATH=($(find "${PROJECT_DIR}" -name 'Instabug.framework.dSYM')) +if [ ! "${Instabug_DSYM_PATH}" ]; then + echo "Instabug: can not find Instabug.framework.dSYM in project directory." +else + cp -r "${Instabug_DSYM_PATH}" "${ARCHIVE_DSYMS_PATH}" + echo "Instabug: Instabug.framework.dSYM successfully copied in project directory." +fi + +InstabugCore_DSYM_PATH=($(find "${PROJECT_DIR}" -name 'InstabugCore.framework.dSYM')) +if [ ! "${InstabugCore_DSYM_PATH}" ]; then +echo "Instabug: can not find InstabugCore.framework.dSYM in project directory." +else +cp -r "${InstabugCore_DSYM_PATH}" "${ARCHIVE_DSYMS_PATH}" +echo "Instabug: InstabugCore.framework.dSYM successfully copied in project directory." +fi + +find "${PROJECT_DIR}" -name "*.bcsymbolmap" | (while read -r file +do + cp -r "${file}" "${ARCHIVE_DSYMS_PATH}/../BCSymbolMaps" +done +) +echo "Instabug: Injecting dSYM and bcsymbolmap inside project archive complete." + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 10.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 10.mom new file mode 100644 index 0000000..8c799ac Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 10.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 11.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 11.mom new file mode 100644 index 0000000..fd441e9 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 11.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 12.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 12.mom new file mode 100644 index 0000000..15414ca Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 12.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.mom new file mode 100644 index 0000000..f690565 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.omo b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.omo new file mode 100644 index 0000000..6b40a21 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.omo differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 2.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 2.mom new file mode 100644 index 0000000..a467c48 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 2.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 3.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 3.mom new file mode 100644 index 0000000..ccfe9f1 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 3.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 7.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 7.mom new file mode 100644 index 0000000..26310c1 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 7.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 8.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 8.mom new file mode 100644 index 0000000..aa45220 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 8.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 9.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 9.mom new file mode 100644 index 0000000..e66e1f4 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 9.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel.mom new file mode 100644 index 0000000..ce7d8be Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/VersionInfo.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/VersionInfo.plist new file mode 100644 index 0000000..4f63d7e Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugDataModel.momd/VersionInfo.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.mom new file mode 100644 index 0000000..d88fb20 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.omo b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.omo new file mode 100644 index 0000000..c1913ae Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.omo differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel.mom b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel.mom new file mode 100644 index 0000000..40bead4 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel.mom differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/VersionInfo.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/VersionInfo.plist new file mode 100644 index 0000000..edd06d6 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/InstabugSurveysDataModel.momd/VersionInfo.plist differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Instabug_dsym_upload.sh b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Instabug_dsym_upload.sh new file mode 100755 index 0000000..56ecb8d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/Instabug_dsym_upload.sh @@ -0,0 +1,161 @@ +#!/bin/bash +# Copyright 2014 Instabug, Inc. All rights reserved. +# +# Usage: +# * In the project editor, select your target. +# * Click "Build Phases" at the top of the project editor. +# * Click "+" button in the top left corner. +# * Choose "New Run Script Build Phase." +# * Uncomment and paste the following script. +# +# --- INVOCATION SCRIPT BEGIN --- +# # SKIP_SIMULATOR_BUILDS=1 +# SCRIPT_SRC=$(find "$PROJECT_DIR" -name 'Instabug_dsym_upload.sh' | head -1) +# if [ ! "${SCRIPT_SRC}" ]; then +# echo "Instabug: err: script not found. Make sure that you're including Instabug.bundle in your project directory" +# exit 1 +# fi +# source "${SCRIPT_SRC}" +# --- INVOCATION SCRIPT END --- + +echo "Instabug: Started uploading dSYM" + +# Check for simulator builds +if [ "$EFFECTIVE_PLATFORM_NAME" == "-iphonesimulator" ]; then + if [ "${SKIP_SIMULATOR_BUILDS}" ] && [ "${SKIP_SIMULATOR_BUILDS}" -eq 1 ]; then + echo "Instabug: Skipping simulator build" + exit 0 + fi +fi + +# Check to make sure the app token exists +# Objective-C +if [ ! "${APP_TOKEN}" ]; then + APP_TOKEN=$(grep -r 'Instabug startWithToken:@\"[0-9a-zA-Z]*\"' ./ -m 1 | grep -o '\"[0-9a-zA-Z]*\"' | cut -d "\"" -f 2) +fi + +# Swift +if [ ! "${APP_TOKEN}" ]; then + APP_TOKEN=$(grep -r 'Instabug.startWithToken(\"[0-9a-zA-Z]*\"' ./ -m 1 | grep -o '\"[0-9a-zA-Z]*\"' | cut -d "\"" -f 2) +fi + +if [ ! "${APP_TOKEN}" ]; then + APP_TOKEN=$(grep -r 'Instabug.start(withToken:\"[0-9a-zA-Z]*\"' ./ -m 1 | grep -o '\"[0-9a-zA-Z]*\"' | cut -d "\"" -f 2) +fi + +if [ ! "${APP_TOKEN}" ] || [ -z "${APP_TOKEN}" ];then + echo "Instabug: err: APP_TOKEN not found. Make sure you've added the SDK initialization line [Instabug startWithToken: invocationEvent:]" + exit 1 +fi +echo "Instabug: found APP_TOKEN=${APP_TOKEN}" + +# Check internet connection +set -x + +CURL_RESPONSE=$(curl 'https://api.instabug.com') + +if [[ $CURL_RESPONSE != *"OK"* ]]; then + echo "ERROR connecting to api.instabug.com." + echo "${CURL_RESPONSE}" + exit 0 +else + echo SUCCESS +fi + +set +x + +# Create temp directory if not exists +CURRENT_USER=$(whoami| tr -dc '[:alnum:]\n\r' | tr '[:upper:]' '[:lower:]') +TEMP_ROOT="/tmp/Instabug-${CURRENT_USER}" +if [ ! -d "${TEMP_ROOT}" ]; then +mkdir "${TEMP_ROOT}" +fi +TEMP_DIRECTORY="${TEMP_ROOT}/$EXECUTABLE_NAME" +if [ ! -d "${TEMP_DIRECTORY}" ]; then +mkdir "${TEMP_DIRECTORY}" +fi + +# Check dSYM file +if [ ! "${DSYM_PATH}" ]; then + if [ ! "${DWARF_DSYM_FOLDER_PATH}" ] || [ ! "${DWARF_DSYM_FILE_NAME}" ]; then + echo "Instabug: err: DWARF_DSYM_FOLDER_PATH or DWARF_DSYM_FILE_NAME not defined" + exit 0 + fi + DSYM_PATH=${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME} +fi +echo "Instabug: found DSYM_PATH=${DSYM_PATH}" + +# Check if UUIDs exists +DSYMS_DIR="${TEMP_DIRECTORY}/dSYM" + +if [ -d "${DSYMS_DIR}" ]; then + rm -rf "${DSYMS_DIR}" +fi + +mkdir "$DSYMS_DIR" +DSYM_UUIDs="" +SEPARATOR=$'\n' +DSYM_UUIDs_PATH="${TEMP_DIRECTORY}/UUIDs.dat" + + +find "${DWARF_DSYM_FOLDER_PATH}" -name "*.dSYM" | (while read -r file +do + UUIDs=$(dwarfdump --uuid "${file}" | cut -d ' ' -f2) + if [ -f "${DSYM_UUIDs_PATH}" ]; then + for uuid in $UUIDs + do + UUIDTOKEN="${uuid}"-"${APP_TOKEN}" + if ! grep -w "${UUIDTOKEN}" "${DSYM_UUIDs_PATH}" ; then + cp -r "${file}" "${DSYMS_DIR}" + DSYM_UUIDs+=$uuid$SEPARATOR + fi + done + else + cp -r "${file}" "${DSYMS_DIR}" + DSYM_UUIDs+=${UUIDs}$SEPARATOR + fi +done + +if [ -z "$DSYM_UUIDs" ]; then + rm -rf "${DSYMS_DIR}" + exit 0 +fi + + +DSYM_UUIDs_TOKEN="${DSYM_UUIDs//${SEPARATOR}/-${APP_TOKEN}$'\n'}" + +# Create dSYM .zip file +DSYM_PATH_ZIP="${TEMP_DIRECTORY}/$DWARF_DSYM_FILE_NAME.zip" +if [ ! -d "$DSYM_PATH" ]; then + echo "Instabug: err: dSYM not found: ${DSYM_PATH}" + exit 0 +fi +echo "Instabug: Compressing dSYM file..." +(/usr/bin/zip --recurse-paths --quiet "${DSYM_PATH_ZIP}" "${DSYMS_DIR}") || exit 0 + +# Upload dSYM +echo "Instabug: Uploading dSYM file..." +ENDPOINT="https://api.instabug.com/api/sdk/v3/symbols_files" +STATUS=$(curl "${ENDPOINT}" --write-out %{http_code} --silent --output /dev/null -F os=iOS -F symbols_file=@"${DSYM_PATH_ZIP}" -F application_token="${APP_TOKEN}") +if [ $STATUS -ne 200 ]; then + echo "Instabug: err: dSYM archive not succesfully uploaded." + echo "Instabug: deleting temporary dSYM archive..." + rm -f "${DSYM_PATH_ZIP}" + exit 0 +fi + +# Remove temp dSYM archive and dSYM DIR +echo "Instabug: deleting temporary dSYM archive..." +rm -f "${DSYM_PATH_ZIP}" +rm -rf "${DSYMS_DIR}" + +# Save UUIDs +echo "${DSYM_UUIDs_TOKEN}" >> "${DSYM_UUIDs_PATH}" + +# Finalize +echo "Instabug: dSYM upload complete." +if [ "$?" -ne 0 ]; then + echo "Instabug: err: an error was encountered uploading dSYM" + exit 0 +fi +) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ar.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ar.lproj/Localizable.strings new file mode 100644 index 0000000..4eefed4 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ar.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/cs.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/cs.lproj/Localizable.strings new file mode 100644 index 0000000..c5dfaa9 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/cs.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/da.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/da.lproj/Localizable.strings new file mode 100644 index 0000000..afb3369 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/da.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/de.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/de.lproj/Localizable.strings new file mode 100644 index 0000000..9d050d0 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/de.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/en.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/en.lproj/Localizable.strings new file mode 100644 index 0000000..bac209e Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/en.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/en.lproj/Localizable.stringsdict b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/en.lproj/Localizable.stringsdict new file mode 100644 index 0000000..3e6913f Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/en.lproj/Localizable.stringsdict differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/es.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/es.lproj/Localizable.strings new file mode 100644 index 0000000..87c4c27 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/es.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/fr.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/fr.lproj/Localizable.strings new file mode 100644 index 0000000..2512d47 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/fr.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/hu.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/hu.lproj/Localizable.strings new file mode 100644 index 0000000..92fab1c Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/hu.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/it.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/it.lproj/Localizable.strings new file mode 100644 index 0000000..57da7aa Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/it.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ja.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ja.lproj/Localizable.strings new file mode 100644 index 0000000..a72797d Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ja.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ko.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ko.lproj/Localizable.strings new file mode 100644 index 0000000..0c6617c Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ko.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/nb.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/nb.lproj/Localizable.strings new file mode 100644 index 0000000..348b7c7 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/nb.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/nl.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/nl.lproj/Localizable.strings new file mode 100644 index 0000000..9d5f7a5 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/nl.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pl.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pl.lproj/Localizable.strings new file mode 100644 index 0000000..ee3f734 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pl.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pt-BR.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pt-BR.lproj/Localizable.strings new file mode 100644 index 0000000..918db92 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pt-BR.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pt-PT.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pt-PT.lproj/Localizable.strings new file mode 100644 index 0000000..0c5faa4 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/pt-PT.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ru.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ru.lproj/Localizable.strings new file mode 100644 index 0000000..0c2e8bf Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/ru.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/sk.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/sk.lproj/Localizable.strings new file mode 100644 index 0000000..f7e0ed0 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/sk.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/sv.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/sv.lproj/Localizable.strings new file mode 100644 index 0000000..6696028 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/sv.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/tr.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/tr.lproj/Localizable.strings new file mode 100644 index 0000000..52a0df3 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/tr.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hans.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..436c811 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hans.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hant-TW.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hant-TW.lproj/Localizable.strings new file mode 100644 index 0000000..b155310 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hant-TW.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hant.lproj/Localizable.strings b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hant.lproj/Localizable.strings new file mode 100644 index 0000000..993f3d7 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/InstabugResources.bundle/zh-Hant.lproj/Localizable.strings differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Modules/module.modulemap b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Modules/module.modulemap new file mode 100644 index 0000000..22c7c5d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module Instabug { + umbrella header "Instabug.h" + + export * + module * { export * } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/_CodeSignature/CodeResources b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/_CodeSignature/CodeResources new file mode 100644 index 0000000..d38a0e7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/_CodeSignature/CodeResources @@ -0,0 +1,1455 @@ + + + + + files + + Headers/IBGBugReporting.h + + YWPQAgj4K5sxqWckjrlKPR7bFY8= + + Headers/IBGChats.h + + bmsbVuevjyKUCEE90EMi+nCeP18= + + Headers/IBGCrashReporting.h + + J+nbZD9XLGOqQ5NKTdmlUS7jT5U= + + Headers/IBGFeatureRequests.h + + luedox/ZnMg237zYJU1UlOJflTw= + + Headers/IBGLog.h + + 200u3KsLqu4ZxJDTSeXWzLtZp7E= + + Headers/IBGNetworkLogger.h + + TnZ7urtGDkIsgGERMaWW2++Qh44= + + Headers/IBGReplies.h + + MNHmLUaPI1mvXGNVB4Me8psvc1A= + + Headers/IBGReport.h + + jqvjTfQzVkTaCt0pZwrQlCAbRXM= + + Headers/IBGSurvey.h + + f9xxYupSdHZNxQm+RHLGAsVfBj0= + + Headers/IBGSurveys.h + + /3YzV8EZEQCezQm4JudRChnpyfk= + + Headers/IBGTypes.h + + Un8QCWVSUebVqEGJARZJSY/Y+90= + + Headers/Instabug.h + + LfSWkk0lm865MA29rn5QVHNLWqM= + + Headers/InstabugCore.h + + 9EVJQc6VeTJU0bdeyFf2JquQyic= + + Headers/UIView+Instabug.h + + 6lNJSaS4jMv4jEUiOIXlTUW8jlA= + + Info.plist + + iwpikTuRZQvsLA5XOVF0O+X0Kh0= + + InstabugResources.bundle/Assets.car + + 2V61Qol6ahwnrCeytKxiCOhXztM= + + InstabugResources.bundle/Config.plist + + zmV6UqBSo6r1NOz798vd5O4zTBA= + + InstabugResources.bundle/IBGActionSheetCell.nib + + Xlx83ieP17qxqW3WMHRiZ9tQ4m4= + + InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/objects-11.0+.nib + + UxUTTn1uV9GDjXEzghsD+jw7ENg= + + InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/runtime.nib + + uvqDNhQ6rvDsfGaCqCegF/UGw7s= + + InstabugResources.bundle/IBGBugVC-iPhone.nib/objects-11.0+.nib + + CDCU4riCokQYKSxiEKwCNFcQSsU= + + InstabugResources.bundle/IBGBugVC-iPhone.nib/runtime.nib + + aWoU2vjPpvXpn6x9p8GrGQrDYtU= + + InstabugResources.bundle/IBGChatCell.nib + + 3tcJoWMafh5E06liNN3Er/PhbOc= + + InstabugResources.bundle/IBGChatListVC-iPhone.nib + + 8R3g84erkKhhYlSsJvoB2OpUmtQ= + + InstabugResources.bundle/IBGChatVC-iPhone.nib/objects-11.0+.nib + + tiTnnseCERBdKdH9aC++rFlYD5A= + + InstabugResources.bundle/IBGChatVC-iPhone.nib/runtime.nib + + mbEufHMCO8xKPdCd28MGdSj7I4Y= + + InstabugResources.bundle/IBGFullScreenImageViewController.nib + + K6Rh6o6+KgX75yjqGdnYXdkngNg= + + InstabugResources.bundle/IBGPoweredByView.nib + + wKVEDzzHIEGysNTNJMG3rwoPnRQ= + + InstabugResources.bundle/IBGPromptCell.nib + + EwKB825G5oiiEPPK/xxb/4J2VEw= + + InstabugResources.bundle/IBGPromptVC-iPhone.nib + + 6Km1ELBWOu24UzqEJuEzfJZU94k= + + InstabugResources.bundle/IBGReplyView-iPhone.nib + + tjTxEpl4OH2Y9o3C3Iy154JlM1w= + + InstabugResources.bundle/IBGReportCategoriesVC-iPhone.nib + + Fy7QDzoXkVuXRrXFnsIquiPfqyk= + + InstabugResources.bundle/IBGScreenshotVC-iPhone.nib + + qtH3hy1TfjYFY+yG1pj5OpQXfgQ= + + InstabugResources.bundle/IBGVideoPlaybackViewController.nib + + nFyV+q/nxzEra3oayiz9m5CnJLA= + + InstabugResources.bundle/IBGVoiceNoteRecordingViewController-iPhone.nib + + YvwaWHIrwVIq2E/BJ82WxyX1pxQ= + + InstabugResources.bundle/Info.plist + + ROQV/UnBi0rPUaeWi9aPJS1QTi8= + + InstabugResources.bundle/Inject_DSYM_Project-Archive.sh + + K+qqKSlG2L7jBTzxekvA8TklxvQ= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 10.mom + + NtIzBzkxwtmIlGVa26zMGx7h9t8= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 11.mom + + xijbM5iakJNIZsEOjCEvlpNP88M= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 12.mom + + fCTQP3x1e78pecuXMGSk71wO30Q= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.mom + + T43MHUm2D+VoZ3oj6mrV+EX07H4= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.omo + + oA70R+9aXlf7A4O3iYhunSj9hC0= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 2.mom + + MAXC3qUm4Hz0GxTPshNHNpdrDaQ= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 3.mom + + jrqCkVaU14U8RPQBdO9pS/0Pk4I= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 7.mom + + 3sQ76HG4DgxopC8dddbOkaenrF8= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 8.mom + + Z8qLTaCqiQMWebQMUeW3XlVxQSc= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 9.mom + + KnURQnAJj79EnjLNGP0Q3LMJmwY= + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel.mom + + 6kSXQ1euyJl1gPfPnihcaMR42X4= + + InstabugResources.bundle/InstabugDataModel.momd/VersionInfo.plist + + zCGijhGlIbm/pkovrgz4BxbFJBA= + + InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.mom + + uPTeQx4GSXNzcCSGt6bnwNtf1MM= + + InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.omo + + yopIoGW4GGbd1D5VBw7PkdZ3FWs= + + InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel.mom + + uuP2ulMvf1OBb5sF/e6DZZM4nIk= + + InstabugResources.bundle/InstabugSurveysDataModel.momd/VersionInfo.plist + + 8Tmdh44XKx/QiNDAjauXNzlBDos= + + InstabugResources.bundle/Instabug_dsym_upload.sh + + YwvQgjUt9aYQ6fnSpWcgegBKAN8= + + InstabugResources.bundle/ar.lproj/Localizable.strings + + hash + + 9f1RDDUslf3DivwEO+VEch5/2dQ= + + optional + + + InstabugResources.bundle/cs.lproj/Localizable.strings + + hash + + GVOx+qIz+wx1pMFZPKjZasKU0Go= + + optional + + + InstabugResources.bundle/da.lproj/Localizable.strings + + hash + + 6aa/jEfB9aeUZTAZ4NVXaHHwHS0= + + optional + + + InstabugResources.bundle/de.lproj/Localizable.strings + + hash + + R3LIRZm4TrOiZb2JnuoSz2mE924= + + optional + + + InstabugResources.bundle/en.lproj/Localizable.strings + + hash + + arg54KsNkDjj1DHLI1KYHbWxEBc= + + optional + + + InstabugResources.bundle/en.lproj/Localizable.stringsdict + + hash + + JT8QT5SebrK2XFFs3Iov80e9WkI= + + optional + + + InstabugResources.bundle/es.lproj/Localizable.strings + + hash + + Z7FFSCU+zbzqUktRmTTMhgh0Q4Q= + + optional + + + InstabugResources.bundle/fr.lproj/Localizable.strings + + hash + + d81lB+jJRhn1k4kBQ7RmruBb8nE= + + optional + + + InstabugResources.bundle/hu.lproj/Localizable.strings + + hash + + qpYWjZz/lCFAeMJclKqVtXW9DTg= + + optional + + + InstabugResources.bundle/it.lproj/Localizable.strings + + hash + + hfh1Dd7V8+Do1p66Py7vUNXxgkM= + + optional + + + InstabugResources.bundle/ja.lproj/Localizable.strings + + hash + + Xn+fZEeLyrw/alRw8TD7whEwiQQ= + + optional + + + InstabugResources.bundle/ko.lproj/Localizable.strings + + hash + + Z6YlCWAkuW2WBNtctqLUuFMK0u8= + + optional + + + InstabugResources.bundle/nb.lproj/Localizable.strings + + hash + + HmDNHqEDi2NWjOZFEyhUzAOojXY= + + optional + + + InstabugResources.bundle/nl.lproj/Localizable.strings + + hash + + YogEC7bBv0lpF6f/gxS4gNNKd1E= + + optional + + + InstabugResources.bundle/pl.lproj/Localizable.strings + + hash + + z7PsQa1h4wCPHmkxbrcH/XzetV0= + + optional + + + InstabugResources.bundle/pt-BR.lproj/Localizable.strings + + hash + + RO2AexTD3RcK5eZqSa53cTn9+Pc= + + optional + + + InstabugResources.bundle/pt-PT.lproj/Localizable.strings + + hash + + Zp01digilcGwOwNVOFx4mnnVsa8= + + optional + + + InstabugResources.bundle/ru.lproj/Localizable.strings + + hash + + s3K5psXnR61A7jaMEt5lb1sS9j4= + + optional + + + InstabugResources.bundle/sk.lproj/Localizable.strings + + hash + + dFK2Z16xpoqNFgfUewwImnI78lA= + + optional + + + InstabugResources.bundle/sv.lproj/Localizable.strings + + hash + + 8dJOopp5YC0/ZWheZHjNUln+144= + + optional + + + InstabugResources.bundle/tr.lproj/Localizable.strings + + hash + + d6kPb87T9vsdo4PpzMfZ3naQkcU= + + optional + + + InstabugResources.bundle/zh-Hans.lproj/Localizable.strings + + hash + + TV9EBp6Ak0TzquOHJxigSWeyKWk= + + optional + + + InstabugResources.bundle/zh-Hant-TW.lproj/Localizable.strings + + hash + + vGhZIpb+zjAUlIOybl3x0/kH70o= + + optional + + + InstabugResources.bundle/zh-Hant.lproj/Localizable.strings + + hash + + anlUg094wk3nIlC9Q9xhIva14cs= + + optional + + + Modules/module.modulemap + + s54rO/plG4RUZ8kXQnWo2++r/vQ= + + strip-frameworks.sh + + +MG0vr81f9BYFi8t9r2Wy0CFRAQ= + + + files2 + + Headers/IBGBugReporting.h + + hash + + YWPQAgj4K5sxqWckjrlKPR7bFY8= + + hash2 + + ag4AdqOKNzW3OyqcJKHK8iNiLTDNtZ+hjKXfHxZeo8o= + + + Headers/IBGChats.h + + hash + + bmsbVuevjyKUCEE90EMi+nCeP18= + + hash2 + + uDI8eym+GBEorE7P0vLDoTnjvc7691XISn0dPdsKzJE= + + + Headers/IBGCrashReporting.h + + hash + + J+nbZD9XLGOqQ5NKTdmlUS7jT5U= + + hash2 + + HUs2+a+2SGjZoROjTaHV04YmCMc6tzAjmRpxsw2rNgE= + + + Headers/IBGFeatureRequests.h + + hash + + luedox/ZnMg237zYJU1UlOJflTw= + + hash2 + + 0yvdkGbtoX5kjkFbpwqnbqUzOwoEajVzllMmw+Cg2sY= + + + Headers/IBGLog.h + + hash + + 200u3KsLqu4ZxJDTSeXWzLtZp7E= + + hash2 + + g7fJdEqurzQJt8/9p4MtDRTK3K+vcMpbla7AJib3ys4= + + + Headers/IBGNetworkLogger.h + + hash + + TnZ7urtGDkIsgGERMaWW2++Qh44= + + hash2 + + cXFSd2/DV1GmL6ATlKqPqK09n0I+MYyuv6TEvpQp9vg= + + + Headers/IBGReplies.h + + hash + + MNHmLUaPI1mvXGNVB4Me8psvc1A= + + hash2 + + msUfZbMBV7A1m2D7l0AebB0Al8w3tL/Yay+t+EIZ9a8= + + + Headers/IBGReport.h + + hash + + jqvjTfQzVkTaCt0pZwrQlCAbRXM= + + hash2 + + paHuVWTQuf118JEXNoo7fYXWGStFAo4OCxYMqQuW1fk= + + + Headers/IBGSurvey.h + + hash + + f9xxYupSdHZNxQm+RHLGAsVfBj0= + + hash2 + + NpBT5tUdWWmyd7mSMSENa8AxHzxULGxV1LCnIitkikU= + + + Headers/IBGSurveys.h + + hash + + /3YzV8EZEQCezQm4JudRChnpyfk= + + hash2 + + 1MjbiQ0FJn8p44KMs9dBr6jf5iB0LULGV8WEa4tf9Ew= + + + Headers/IBGTypes.h + + hash + + Un8QCWVSUebVqEGJARZJSY/Y+90= + + hash2 + + YmHtgG8EVaWXwIbm6PVpj1uJ5jqjOgJJ41hnJyvcR/I= + + + Headers/Instabug.h + + hash + + LfSWkk0lm865MA29rn5QVHNLWqM= + + hash2 + + nP9LLhZvLJ8Z/g0W+gsax45LYqOEes0rl6wqfjoam2M= + + + Headers/InstabugCore.h + + hash + + 9EVJQc6VeTJU0bdeyFf2JquQyic= + + hash2 + + WCzQmE/GS83yrEf5D8qc/W8SP4IOgLW8qsx5+0WZ9k0= + + + Headers/UIView+Instabug.h + + hash + + 6lNJSaS4jMv4jEUiOIXlTUW8jlA= + + hash2 + + k2jyV22dpiYArGAYKkfuW5TDrEEOfjq63h9FLt4QSZs= + + + InstabugResources.bundle/Assets.car + + hash + + 2V61Qol6ahwnrCeytKxiCOhXztM= + + hash2 + + ldxFKb3SL4K60qJStDAhFnRwplfdvgG3KMPVevWpGko= + + + InstabugResources.bundle/Config.plist + + hash + + zmV6UqBSo6r1NOz798vd5O4zTBA= + + hash2 + + kmHsztpgjvF0JW5f3HdMHm49z1M0CcG8OT1JDQHHE/E= + + + InstabugResources.bundle/IBGActionSheetCell.nib + + hash + + Xlx83ieP17qxqW3WMHRiZ9tQ4m4= + + hash2 + + HYFfCVSuKiK6HmUMD0xeYxEprD/+I8tANMWYUezwATc= + + + InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/objects-11.0+.nib + + hash + + UxUTTn1uV9GDjXEzghsD+jw7ENg= + + hash2 + + ls3pz1/JHFX3QBj30B/3aSJwHlln/tNV4A/Q+77vAKs= + + + InstabugResources.bundle/IBGActionSheetVC-iPhone.nib/runtime.nib + + hash + + uvqDNhQ6rvDsfGaCqCegF/UGw7s= + + hash2 + + +EtS1WpcKFfRzqnSsACNGrefWP1UktO+d0NCDYAZkNs= + + + InstabugResources.bundle/IBGBugVC-iPhone.nib/objects-11.0+.nib + + hash + + CDCU4riCokQYKSxiEKwCNFcQSsU= + + hash2 + + 696PPcUEqnmw8pbA0h2qoJiJxks0QwO7VwGhp8ejuzo= + + + InstabugResources.bundle/IBGBugVC-iPhone.nib/runtime.nib + + hash + + aWoU2vjPpvXpn6x9p8GrGQrDYtU= + + hash2 + + z7GrjTaci6lFnszD3QbfqM6XJ7pRWEv7/NpLVYOJeLU= + + + InstabugResources.bundle/IBGChatCell.nib + + hash + + 3tcJoWMafh5E06liNN3Er/PhbOc= + + hash2 + + 76vfcYe0DoJSvLQGAbQrYXPZGFRzdrwlng1i7wENXXg= + + + InstabugResources.bundle/IBGChatListVC-iPhone.nib + + hash + + 8R3g84erkKhhYlSsJvoB2OpUmtQ= + + hash2 + + YjP62KPFCDCBe3B97gPxID3DjXTvS66NgiVRQy9tduU= + + + InstabugResources.bundle/IBGChatVC-iPhone.nib/objects-11.0+.nib + + hash + + tiTnnseCERBdKdH9aC++rFlYD5A= + + hash2 + + dNduL+GEUHQNJ/QhEEs7+IBhbaOHsIoggxQzfi8XtKo= + + + InstabugResources.bundle/IBGChatVC-iPhone.nib/runtime.nib + + hash + + mbEufHMCO8xKPdCd28MGdSj7I4Y= + + hash2 + + TYT9qq4YHo/4JfSjllV3sn6eOfEchKtWm+uIt2bKPYQ= + + + InstabugResources.bundle/IBGFullScreenImageViewController.nib + + hash + + K6Rh6o6+KgX75yjqGdnYXdkngNg= + + hash2 + + 2mPO7j7mrEa5M0XRfvIUvMqfflYsL69R5+Dxi+RXWow= + + + InstabugResources.bundle/IBGPoweredByView.nib + + hash + + wKVEDzzHIEGysNTNJMG3rwoPnRQ= + + hash2 + + Tjzl+2fOFkJcyHjZGQP6OpQ96fR1BWRbvSMKCrxJoyY= + + + InstabugResources.bundle/IBGPromptCell.nib + + hash + + EwKB825G5oiiEPPK/xxb/4J2VEw= + + hash2 + + P+8sjWcb6QepUIaTYmolyxnWCfkRGRr6Urbh6BHquz4= + + + InstabugResources.bundle/IBGPromptVC-iPhone.nib + + hash + + 6Km1ELBWOu24UzqEJuEzfJZU94k= + + hash2 + + yUkIY1oJ0BlIUhqKygQDX/C+DZehuU2cCMV3rkaszqw= + + + InstabugResources.bundle/IBGReplyView-iPhone.nib + + hash + + tjTxEpl4OH2Y9o3C3Iy154JlM1w= + + hash2 + + weXGA2zR3xC5Pm2I7r51UT+3MAWprfsaYbt/mDc8NVg= + + + InstabugResources.bundle/IBGReportCategoriesVC-iPhone.nib + + hash + + Fy7QDzoXkVuXRrXFnsIquiPfqyk= + + hash2 + + vEdbsBKr+/gTEr2oFzfMnYaS2jeBQUETRNwKcrJsHh8= + + + InstabugResources.bundle/IBGScreenshotVC-iPhone.nib + + hash + + qtH3hy1TfjYFY+yG1pj5OpQXfgQ= + + hash2 + + J6Yv6FnVkC/+s1M51FTBmeCU5hlONIwJzDYL9gf9Ckw= + + + InstabugResources.bundle/IBGVideoPlaybackViewController.nib + + hash + + nFyV+q/nxzEra3oayiz9m5CnJLA= + + hash2 + + M112EfkSEFR6FxoOCpiZ1KtLXtJ4bqIbFU2woqEavRE= + + + InstabugResources.bundle/IBGVoiceNoteRecordingViewController-iPhone.nib + + hash + + YvwaWHIrwVIq2E/BJ82WxyX1pxQ= + + hash2 + + dOLX1ySfUrfrCcdV0WNyos4333phOY+lBNWnBKMFNeg= + + + InstabugResources.bundle/Info.plist + + hash + + ROQV/UnBi0rPUaeWi9aPJS1QTi8= + + hash2 + + 3VTT54xsZWKWq8ZASntrE0ReBXOu098FDrph8NQRxLE= + + + InstabugResources.bundle/Inject_DSYM_Project-Archive.sh + + hash + + K+qqKSlG2L7jBTzxekvA8TklxvQ= + + hash2 + + STmY6jc7rqCtoJkhAzZah2dRtLkU77lmbhULW/xd9wo= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 10.mom + + hash + + NtIzBzkxwtmIlGVa26zMGx7h9t8= + + hash2 + + Sr/Mv/QEnoWJRwX1rFxRmpPboUmRVNIl8e53mZeHaPM= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 11.mom + + hash + + xijbM5iakJNIZsEOjCEvlpNP88M= + + hash2 + + NR9ZtMdFtKQs6iBgVVJTVcjO20dB4GzQR9Md5vGi/cs= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 12.mom + + hash + + fCTQP3x1e78pecuXMGSk71wO30Q= + + hash2 + + KBYFIfXBVYh3prnbK+jWNfLWuaBrb80x3bth2niLjig= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.mom + + hash + + T43MHUm2D+VoZ3oj6mrV+EX07H4= + + hash2 + + zAd4V1PDDdy5q8OdWg9V2PPdn5m6JFKbRIpeH9RpGmE= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 14.omo + + hash + + oA70R+9aXlf7A4O3iYhunSj9hC0= + + hash2 + + 5RoEiGNQISR9j/pqjVxyOBRYj6XARkbLAQiTW6gLmJw= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 2.mom + + hash + + MAXC3qUm4Hz0GxTPshNHNpdrDaQ= + + hash2 + + 2rEJvrNh5C/jr6PA9Xorm67ZLMCnM4NTZmvCj1Y0ORQ= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 3.mom + + hash + + jrqCkVaU14U8RPQBdO9pS/0Pk4I= + + hash2 + + pic6pqmCe3o1i/PGdHjX4QFhxkA+6K/4hpI8G0HhoFA= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 7.mom + + hash + + 3sQ76HG4DgxopC8dddbOkaenrF8= + + hash2 + + LzCp1euKwcnCJSQAkugSCTQUzOIHQJjg9wljfYcs+tg= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 8.mom + + hash + + Z8qLTaCqiQMWebQMUeW3XlVxQSc= + + hash2 + + f/dvnHZkel669rD2DaKYRhBM6+Hay+17coFa/Pl8NwY= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel 9.mom + + hash + + KnURQnAJj79EnjLNGP0Q3LMJmwY= + + hash2 + + nW0gYK5E7htGqg+G8zpBYlwIlq5HTkgBbMXEAC6xZ2c= + + + InstabugResources.bundle/InstabugDataModel.momd/InstabugDataModel.mom + + hash + + 6kSXQ1euyJl1gPfPnihcaMR42X4= + + hash2 + + Rch/x/qp0RsZkJlj+D3NK15uhxv3R3uOAjxV1mNvGjU= + + + InstabugResources.bundle/InstabugDataModel.momd/VersionInfo.plist + + hash + + zCGijhGlIbm/pkovrgz4BxbFJBA= + + hash2 + + 0AGg41xsTwNwp2PHsQ/P+o5Blgxg17iZOVLcwDbdaZk= + + + InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.mom + + hash + + uPTeQx4GSXNzcCSGt6bnwNtf1MM= + + hash2 + + Y4WNm//imxCh2r+OO+NSPN9SwAFJeQ3wg8HCVCtVKyQ= + + + InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel 2.omo + + hash + + yopIoGW4GGbd1D5VBw7PkdZ3FWs= + + hash2 + + yom9VxhtBsoSG4VyQn1jnyNWqMz7PqWjc9gSH32GydE= + + + InstabugResources.bundle/InstabugSurveysDataModel.momd/InstabugSurveysDataModel.mom + + hash + + uuP2ulMvf1OBb5sF/e6DZZM4nIk= + + hash2 + + dRzPUxYH+GA5RH825AVP3bGG6w17zyYuTikpYjTnEQI= + + + InstabugResources.bundle/InstabugSurveysDataModel.momd/VersionInfo.plist + + hash + + 8Tmdh44XKx/QiNDAjauXNzlBDos= + + hash2 + + urqi3bfkzG1tyM47g1DhReAL3+imHl1tiAnR0IpljBU= + + + InstabugResources.bundle/Instabug_dsym_upload.sh + + hash + + YwvQgjUt9aYQ6fnSpWcgegBKAN8= + + hash2 + + LeDN56flghL0QyoiM1P3OOyaA/NJvWoaENzzj4/+OxM= + + + InstabugResources.bundle/ar.lproj/Localizable.strings + + hash + + 9f1RDDUslf3DivwEO+VEch5/2dQ= + + hash2 + + FBPI2rq69HDn2p7cHp8MJJgdb+MxD1GM/62H/ZXJz8g= + + optional + + + InstabugResources.bundle/cs.lproj/Localizable.strings + + hash + + GVOx+qIz+wx1pMFZPKjZasKU0Go= + + hash2 + + NTifLdfWl/njaUXNyFhG7m88TaqikgmhYe9RgC6szIc= + + optional + + + InstabugResources.bundle/da.lproj/Localizable.strings + + hash + + 6aa/jEfB9aeUZTAZ4NVXaHHwHS0= + + hash2 + + 9CHh1zHwGbsa7sjufZw3DqgM1abPKLwJMHLRfPWWSf4= + + optional + + + InstabugResources.bundle/de.lproj/Localizable.strings + + hash + + R3LIRZm4TrOiZb2JnuoSz2mE924= + + hash2 + + UULryqdcdekV5V8dRzAGV08VpC6oFI3ZKAyfu6O7qkA= + + optional + + + InstabugResources.bundle/en.lproj/Localizable.strings + + hash + + arg54KsNkDjj1DHLI1KYHbWxEBc= + + hash2 + + lN7O45lXKNLZ0X+ctLb6qTpg3P7bTKuoMxSO2XbBklo= + + optional + + + InstabugResources.bundle/en.lproj/Localizable.stringsdict + + hash + + JT8QT5SebrK2XFFs3Iov80e9WkI= + + hash2 + + Lr6rDy8EAt8S8WL0sGd9Nn5eViv3p1dMB5ttvTej0fk= + + optional + + + InstabugResources.bundle/es.lproj/Localizable.strings + + hash + + Z7FFSCU+zbzqUktRmTTMhgh0Q4Q= + + hash2 + + 8XEMAwxWH0t9zQwiUGM4omvM0espUUUMuMJ5xN+48nM= + + optional + + + InstabugResources.bundle/fr.lproj/Localizable.strings + + hash + + d81lB+jJRhn1k4kBQ7RmruBb8nE= + + hash2 + + augldkYJMJbw+IDNu1TVCAmauFzYpBqGjgmpKK4Rl/c= + + optional + + + InstabugResources.bundle/hu.lproj/Localizable.strings + + hash + + qpYWjZz/lCFAeMJclKqVtXW9DTg= + + hash2 + + XB6gD5uuSbFPaZug4JeWn73nVUHOnsMMyzeEy4yGEcI= + + optional + + + InstabugResources.bundle/it.lproj/Localizable.strings + + hash + + hfh1Dd7V8+Do1p66Py7vUNXxgkM= + + hash2 + + 0Ivc6a2QiGBcpr62tv/4JFPKaPvGrL0bTHLLHRx6buw= + + optional + + + InstabugResources.bundle/ja.lproj/Localizable.strings + + hash + + Xn+fZEeLyrw/alRw8TD7whEwiQQ= + + hash2 + + W2O4BV0KekFfs3esigEQh7blLevQ2dSI/z8/S1fFfss= + + optional + + + InstabugResources.bundle/ko.lproj/Localizable.strings + + hash + + Z6YlCWAkuW2WBNtctqLUuFMK0u8= + + hash2 + + BW32/dPcfbwUp56+hMRxfY/Y/JEYppETzSyD3sAW92s= + + optional + + + InstabugResources.bundle/nb.lproj/Localizable.strings + + hash + + HmDNHqEDi2NWjOZFEyhUzAOojXY= + + hash2 + + KCn+QSetmfoQkTOXzvfl9tKZH9Hs8Y0WmW4gYjXwf7o= + + optional + + + InstabugResources.bundle/nl.lproj/Localizable.strings + + hash + + YogEC7bBv0lpF6f/gxS4gNNKd1E= + + hash2 + + SGCTLRKawt0/KN86H5NxS4Oolzo6SGslcm5+IVZJsV0= + + optional + + + InstabugResources.bundle/pl.lproj/Localizable.strings + + hash + + z7PsQa1h4wCPHmkxbrcH/XzetV0= + + hash2 + + M2hvrIBdIa1P0wEsJy8GCmkeXrXBVcUmJARdrZn8Boc= + + optional + + + InstabugResources.bundle/pt-BR.lproj/Localizable.strings + + hash + + RO2AexTD3RcK5eZqSa53cTn9+Pc= + + hash2 + + rN5PJoUUeH4hdF5cKVRdC9pfX0LfnNQ1aRh7sq2MMOs= + + optional + + + InstabugResources.bundle/pt-PT.lproj/Localizable.strings + + hash + + Zp01digilcGwOwNVOFx4mnnVsa8= + + hash2 + + 0w9A9+ZLubwOKBrHu5DtmofoogYzaYaYKixESyGu2Vo= + + optional + + + InstabugResources.bundle/ru.lproj/Localizable.strings + + hash + + s3K5psXnR61A7jaMEt5lb1sS9j4= + + hash2 + + Qxs0SYHS3sFl4QVAAPa3tSzRW4XIOjBiPW0l60zjGtQ= + + optional + + + InstabugResources.bundle/sk.lproj/Localizable.strings + + hash + + dFK2Z16xpoqNFgfUewwImnI78lA= + + hash2 + + 1RObdlaT1ubXSaXfPd6f7PQSFgL9XYtGvNXf15UUcrY= + + optional + + + InstabugResources.bundle/sv.lproj/Localizable.strings + + hash + + 8dJOopp5YC0/ZWheZHjNUln+144= + + hash2 + + PmTvoWj0j/0+N4sw1zXfhCWn6DUVDE181S6eq0EPzCI= + + optional + + + InstabugResources.bundle/tr.lproj/Localizable.strings + + hash + + d6kPb87T9vsdo4PpzMfZ3naQkcU= + + hash2 + + Ox1JUsaOm3tl5XL4LTpmL4r1vgqA3AW+9ldyK0MOv+o= + + optional + + + InstabugResources.bundle/zh-Hans.lproj/Localizable.strings + + hash + + TV9EBp6Ak0TzquOHJxigSWeyKWk= + + hash2 + + RmA/jMOsRNy3sHmKUmaLOzsY6suCMtrFFEkFpfHUbaE= + + optional + + + InstabugResources.bundle/zh-Hant-TW.lproj/Localizable.strings + + hash + + vGhZIpb+zjAUlIOybl3x0/kH70o= + + hash2 + + VQgaaM8YINovAHow3pWrFMF0Ijdag1eDgK//O6q8Uow= + + optional + + + InstabugResources.bundle/zh-Hant.lproj/Localizable.strings + + hash + + anlUg094wk3nIlC9Q9xhIva14cs= + + hash2 + + DgaPhn+ZQSoGz/v5dgkG/az/7GYCcSzeFoEn6d9H3ao= + + optional + + + Modules/module.modulemap + + hash + + s54rO/plG4RUZ8kXQnWo2++r/vQ= + + hash2 + + DK65cQ5p1RuqPdi0Jm5KqffATt5qZgprNdPs2BfI0zE= + + + strip-frameworks.sh + + hash + + +MG0vr81f9BYFi8t9r2Wy0CFRAQ= + + hash2 + + EFBdsgIKkcB/ZW5AgcnnL3/o0Bpiv6XiPi3sPZMaPdg= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/strip-frameworks.sh b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/strip-frameworks.sh new file mode 100644 index 0000000..2c23237 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/Instabug.framework/strip-frameworks.sh @@ -0,0 +1,62 @@ +################################################################################ +# +# Copyright 2015 Realm Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +# This script strips all non-valid architectures from dynamic libraries in +# the application's `Frameworks` directory. +# +# The following environment variables are required: +# +# BUILT_PRODUCTS_DIR +# FRAMEWORKS_FOLDER_PATH +# VALID_ARCHS +# EXPANDED_CODE_SIGN_IDENTITY + + +# Signs a framework with the provided identity +code_sign() { +# Use the current code_sign_identitiy +echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" +echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1" +/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" +} + +echo "Stripping frameworks" +cd "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +for file in $(find . -type f -perm +111); do +# Skip non-dynamic libraries +if ! [[ "$(file "$file")" == *"dynamically linked shared library"* ]]; then +continue +fi +# Get architectures for current file +archs="$(lipo -info "${file}" | rev | cut -d ':' -f1 | rev)" +stripped="" +for arch in $archs; do +if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then +# Strip non-valid architectures in-place +lipo -remove "$arch" -output "$file" "$file" || exit 1 +stripped="$stripped $arch" +fi +done +if [[ "$stripped" != "" ]]; then +echo "Stripped $file of architectures:$stripped" +if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then +code_sign "${file}" +fi +fi +done diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/LICENSE.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/LICENSE.md new file mode 100644 index 0000000..7101dae --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/LICENSE.md @@ -0,0 +1,10 @@ +Copyright (C) 2014 Instabug Permission is hereby granted to use this framework as is, modification are not allowed. +All rights reserved. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/README.md new file mode 100644 index 0000000..512e304 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Instabug/README.md @@ -0,0 +1,98 @@ +# Instabug iOS SDK +![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Instabug.svg) +![Twitter](https://img.shields.io/badge/twitter-@Instabug-blue.svg) + +Instabug is an in-app feedback and bug reporting tool for mobile apps. With just a simple shake, your users or beta testers can [report bugs](https://instabug.com/bug-reporting) or send in-app feedback and the SDK will capture an environment snapshot of your user's device including all console logs, [server-side network requests](https://instabug.com/network-logging) and bug reproduction steps compiling all these details in one organised dashboard to help you debug and fix bugs faster. + +Instabug also provides you with a [reliable crash reporter](https://instabug.com/crash-reporting) that automatically captures a detailed report of the running environment, the different threads’ states, [the steps to reproduce the crash](https://instabug.com/user-steps), and the network request logs. All the data is captured automatically with no need for breadcrumbs, and you can always [reply back to your users](https://instabug.com/in-app-chat) and they will receive your messages within the app. + +For more info, visit [Instabug.com](https://www.instabug.com). + +## Installation + +### CocoaPods + +To integrate Instabug into your Xcode project using [CocoaPods](https://cocoapods.org), add it to your `Podfile`: + +```ruby +pod 'Instabug' +``` + +Then, run the following command: + +```bash +$ pod install +``` + +### Carthage + +To integrate Instabug into your Xcode project using [Carthage](https://github.com/Carthage/Carthage), add it to your `Cartfile`: + +``` +binary "https://raw.githubusercontent.com/Instabug/Instabug-iOS/master/Instabug.json" +``` + +Then, run the following command: + +```bash +$ carthage update +``` + +Then drag Instabug.framework into your Xcode project. + +### Manually + +1. [Download the Instabug SDK](https://s3.amazonaws.com/instabug-pro/sdk_releases/Instabug.zip) + +2. Extract it then drag & drop Instabug.framework to your project's "Embedded Binaries" section under the "General" tab, and make sure that the "Copy items if needed" checkbox is checked + +3. Create a new "Run Script Phase" in your project’s target "Build Phases" and add the following snippet + +``` +bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Instabug.framework/strip-frameworks.sh" +``` + +## Usage + +1. Import Instabug framework header in your app delegate + + ```swift + // Swift + import Instabug + ``` + + ```objective-c + // Objective-C + #import + ``` + +2. Add the following to your app delegate's application:didFinishLaunchingWithOptions: method. + + ```swift + // Swift + Instabug.start(withToken: <#app token#>, invocationEvent: .shake) + ``` + ```objective-c + // Objective-C + [Instabug startWithToken:<#app token#> invocationEvent:IBGInvocationEventShake]; + ``` + Make sure to replace `app_token` with your application token. Find it [here](https://instabug.com/app/sdk/). + +## Notes +Instabug needs access to the microphone and photo library to be able to let users add audio and video attachments. Starting from iOS 10, apps that don’t provide a usage description for those 2 permissions would be rejected when submitted to the App Store. + +For your app not to be rejected, you’ll need to add the following 2 keys to your app’s info.plist file with text explaining to the user why those permissions are needed: + +* `NSMicrophoneUsageDescription` +* `NSPhotoLibraryUsageDescription` + +If your app doesn’t already access the microphone or photo library, we recommend using a usage description like: + +* "`` needs access to the microphone to be able to attach voice notes." +* "`` needs access to your photo library for you to be able to attach images." + +**The permission alert for accessing the microphone/photo library will NOT appear unless users attempt to attach a voice note/photo while using Instabug.** + +## More + +You can also check out our [API Reference](https://instabug.com/public/ios-api-reference/Classes/Instabug.html) for more detailed information about our SDK. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/LICENSE new file mode 100644 index 0000000..7ab2a8e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 kishikawa katsumi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/Lib/KeychainAccess/Keychain.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/Lib/KeychainAccess/Keychain.swift new file mode 100644 index 0000000..a2a1789 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/Lib/KeychainAccess/Keychain.swift @@ -0,0 +1,2933 @@ +// +// Keychain.swift +// KeychainAccess +// +// Created by kishikawa katsumi on 2014/12/24. +// Copyright (c) 2014 kishikawa katsumi. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation +import Security +#if os(iOS) || os(OSX) +import LocalAuthentication +#endif + +public let KeychainAccessErrorDomain = "com.kishikawakatsumi.KeychainAccess.error" + +public enum ItemClass { + case genericPassword + case internetPassword +} + +public enum ProtocolType { + case ftp + case ftpAccount + case http + case irc + case nntp + case pop3 + case smtp + case socks + case imap + case ldap + case appleTalk + case afp + case telnet + case ssh + case ftps + case https + case httpProxy + case httpsProxy + case ftpProxy + case smb + case rtsp + case rtspProxy + case daap + case eppc + case ipp + case nntps + case ldaps + case telnetS + case imaps + case ircs + case pop3S +} + +public enum AuthenticationType { + case ntlm + case msn + case dpa + case rpa + case httpBasic + case httpDigest + case htmlForm + case `default` +} + +public enum Accessibility { + /** + Item data can only be accessed + while the device is unlocked. This is recommended for items that only + need be accesible while the application is in the foreground. Items + with this attribute will migrate to a new device when using encrypted + backups. + */ + case whenUnlocked + + /** + Item data can only be + accessed once the device has been unlocked after a restart. This is + recommended for items that need to be accesible by background + applications. Items with this attribute will migrate to a new device + when using encrypted backups. + */ + case afterFirstUnlock + + /** + Item data can always be accessed + regardless of the lock state of the device. This is not recommended + for anything except system use. Items with this attribute will migrate + to a new device when using encrypted backups. + */ + case always + + /** + Item data can + only be accessed while the device is unlocked. This class is only + available if a passcode is set on the device. This is recommended for + items that only need to be accessible while the application is in the + foreground. Items with this attribute will never migrate to a new + device, so after a backup is restored to a new device, these items + will be missing. No items can be stored in this class on devices + without a passcode. Disabling the device passcode will cause all + items in this class to be deleted. + */ + @available(iOS 8.0, OSX 10.10, *) + case whenPasscodeSetThisDeviceOnly + + /** + Item data can only + be accessed while the device is unlocked. This is recommended for items + that only need be accesible while the application is in the foreground. + Items with this attribute will never migrate to a new device, so after + a backup is restored to a new device, these items will be missing. + */ + case whenUnlockedThisDeviceOnly + + /** + Item data can + only be accessed once the device has been unlocked after a restart. + This is recommended for items that need to be accessible by background + applications. Items with this attribute will never migrate to a new + device, so after a backup is restored to a new device these items will + be missing. + */ + case afterFirstUnlockThisDeviceOnly + + /** + Item data can always + be accessed regardless of the lock state of the device. This option + is not recommended for anything except system use. Items with this + attribute will never migrate to a new device, so after a backup is + restored to a new device, these items will be missing. + */ + case alwaysThisDeviceOnly +} + +public struct AuthenticationPolicy: OptionSet { + /** + User presence policy using Touch ID or Passcode. Touch ID does not + have to be available or enrolled. Item is still accessible by Touch ID + even if fingers are added or removed. + */ + @available(iOS 8.0, OSX 10.10, *) + @available(watchOS, unavailable) + public static let userPresence = AuthenticationPolicy(rawValue: 1 << 0) + + /** + Constraint: Touch ID (any finger). Touch ID must be available and + at least one finger must be enrolled. Item is still accessible by + Touch ID even if fingers are added or removed. + */ + @available(iOS 9.0, *) + @available(OSX, unavailable) + @available(watchOS, unavailable) + public static let touchIDAny = AuthenticationPolicy(rawValue: 1 << 1) + + /** + Constraint: Touch ID from the set of currently enrolled fingers. + Touch ID must be available and at least one finger must be enrolled. + When fingers are added or removed, the item is invalidated. + */ + @available(iOS 9.0, *) + @available(OSX, unavailable) + @available(watchOS, unavailable) + public static let touchIDCurrentSet = AuthenticationPolicy(rawValue: 1 << 3) + + /** + Constraint: Device passcode + */ + @available(iOS 9.0, OSX 10.11, *) + @available(watchOS, unavailable) + public static let devicePasscode = AuthenticationPolicy(rawValue: 1 << 4) + + /** + Constraint logic operation: when using more than one constraint, + at least one of them must be satisfied. + */ + @available(iOS 9.0, *) + @available(OSX, unavailable) + @available(watchOS, unavailable) + public static let or = AuthenticationPolicy(rawValue: 1 << 14) + + /** + Constraint logic operation: when using more than one constraint, + all must be satisfied. + */ + @available(iOS 9.0, *) + @available(OSX, unavailable) + @available(watchOS, unavailable) + public static let and = AuthenticationPolicy(rawValue: 1 << 15) + + /** + Create access control for private key operations (i.e. sign operation) + */ + @available(iOS 9.0, *) + @available(OSX, unavailable) + @available(watchOS, unavailable) + public static let privateKeyUsage = AuthenticationPolicy(rawValue: 1 << 30) + + /** + Security: Application provided password for data encryption key generation. + This is not a constraint but additional item encryption mechanism. + */ + @available(iOS 9.0, *) + @available(OSX, unavailable) + @available(watchOS, unavailable) + public static let applicationPassword = AuthenticationPolicy(rawValue: 1 << 31) + + #if swift(>=2.3) + public let rawValue: UInt + + public init(rawValue: UInt) { + self.rawValue = rawValue + } + #else + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + #endif +} + +public struct Attributes { + public var `class`: String? { + return attributes[Class] as? String + } + public var data: Data? { + return attributes[ValueData] as? Data + } + public var ref: Data? { + return attributes[ValueRef] as? Data + } + public var persistentRef: Data? { + return attributes[ValuePersistentRef] as? Data + } + + public var accessible: String? { + return attributes[AttributeAccessible] as? String + } + public var accessControl: SecAccessControl? { + if #available(OSX 10.10, *) { + if let accessControl = attributes[AttributeAccessControl] { + return (accessControl as! SecAccessControl) + } + return nil + } else { + return nil + } + } + public var accessGroup: String? { + return attributes[AttributeAccessGroup] as? String + } + public var synchronizable: Bool? { + return attributes[AttributeSynchronizable] as? Bool + } + public var creationDate: Date? { + return attributes[AttributeCreationDate] as? Date + } + public var modificationDate: Date? { + return attributes[AttributeModificationDate] as? Date + } + public var attributeDescription: String? { + return attributes[AttributeDescription] as? String + } + public var comment: String? { + return attributes[AttributeComment] as? String + } + public var creator: String? { + return attributes[AttributeCreator] as? String + } + public var type: String? { + return attributes[AttributeType] as? String + } + public var label: String? { + return attributes[AttributeLabel] as? String + } + public var isInvisible: Bool? { + return attributes[AttributeIsInvisible] as? Bool + } + public var isNegative: Bool? { + return attributes[AttributeIsNegative] as? Bool + } + public var account: String? { + return attributes[AttributeAccount] as? String + } + public var service: String? { + return attributes[AttributeService] as? String + } + public var generic: Data? { + return attributes[AttributeGeneric] as? Data + } + public var securityDomain: String? { + return attributes[AttributeSecurityDomain] as? String + } + public var server: String? { + return attributes[AttributeServer] as? String + } + public var `protocol`: String? { + return attributes[AttributeProtocol] as? String + } + public var authenticationType: String? { + return attributes[AttributeAuthenticationType] as? String + } + public var port: Int? { + return attributes[AttributePort] as? Int + } + public var path: String? { + return attributes[AttributePath] as? String + } + + fileprivate let attributes: [String: Any] + + init(attributes: [String: Any]) { + self.attributes = attributes + } + + public subscript(key: String) -> Any? { + get { + return attributes[key] + } + } +} + +public final class Keychain { + public var itemClass: ItemClass { + return options.itemClass + } + + public var service: String { + return options.service + } + + public var accessGroup: String? { + return options.accessGroup + } + + public var server: URL { + return options.server + } + + public var protocolType: ProtocolType { + return options.protocolType + } + + public var authenticationType: AuthenticationType { + return options.authenticationType + } + + public var accessibility: Accessibility { + return options.accessibility + } + + @available(iOS 8.0, OSX 10.10, *) + @available(watchOS, unavailable) + public var authenticationPolicy: AuthenticationPolicy? { + return options.authenticationPolicy + } + + public var synchronizable: Bool { + return options.synchronizable + } + + public var label: String? { + return options.label + } + + public var comment: String? { + return options.comment + } + + @available(iOS 8.0, OSX 10.10, *) + @available(watchOS, unavailable) + public var authenticationPrompt: String? { + return options.authenticationPrompt + } + + #if os(iOS) || os(OSX) + @available(iOS 9.0, OSX 10.11, *) + public var authenticationContext: LAContext? { + return options.authenticationContext as? LAContext + } + #endif + + fileprivate let options: Options + + // MARK: + + public convenience init() { + var options = Options() + if let bundleIdentifier = Bundle.main.bundleIdentifier { + options.service = bundleIdentifier + } + self.init(options) + } + + public convenience init(service: String) { + var options = Options() + options.service = service + self.init(options) + } + + public convenience init(accessGroup: String) { + var options = Options() + if let bundleIdentifier = Bundle.main.bundleIdentifier { + options.service = bundleIdentifier + } + options.accessGroup = accessGroup + self.init(options) + } + + public convenience init(service: String, accessGroup: String) { + var options = Options() + options.service = service + options.accessGroup = accessGroup + self.init(options) + } + + public convenience init(server: String, protocolType: ProtocolType, authenticationType: AuthenticationType = .default) { + self.init(server: URL(string: server)!, protocolType: protocolType, authenticationType: authenticationType) + } + + public convenience init(server: URL, protocolType: ProtocolType, authenticationType: AuthenticationType = .default) { + var options = Options() + options.itemClass = .internetPassword + options.server = server + options.protocolType = protocolType + options.authenticationType = authenticationType + self.init(options) + } + + fileprivate init(_ opts: Options) { + options = opts + } + + // MARK: + + public func accessibility(_ accessibility: Accessibility) -> Keychain { + var options = self.options + options.accessibility = accessibility + return Keychain(options) + } + + @available(iOS 8.0, OSX 10.10, *) + @available(watchOS, unavailable) + public func accessibility(_ accessibility: Accessibility, authenticationPolicy: AuthenticationPolicy) -> Keychain { + var options = self.options + options.accessibility = accessibility + options.authenticationPolicy = authenticationPolicy + return Keychain(options) + } + + public func synchronizable(_ synchronizable: Bool) -> Keychain { + var options = self.options + options.synchronizable = synchronizable + return Keychain(options) + } + + public func label(_ label: String) -> Keychain { + var options = self.options + options.label = label + return Keychain(options) + } + + public func comment(_ comment: String) -> Keychain { + var options = self.options + options.comment = comment + return Keychain(options) + } + + public func attributes(_ attributes: [String: Any]) -> Keychain { + var options = self.options + attributes.forEach { options.attributes.updateValue($1, forKey: $0) } + return Keychain(options) + } + + @available(iOS 8.0, OSX 10.10, *) + @available(watchOS, unavailable) + public func authenticationPrompt(_ authenticationPrompt: String) -> Keychain { + var options = self.options + options.authenticationPrompt = authenticationPrompt + return Keychain(options) + } + + #if os(iOS) || os(OSX) + @available(iOS 9.0, OSX 10.11, *) + public func authenticationContext(_ authenticationContext: LAContext) -> Keychain { + var options = self.options + options.authenticationContext = authenticationContext + return Keychain(options) + } + #endif + + // MARK: + + public func get(_ key: String) throws -> String? { + return try getString(key) + } + + public func getString(_ key: String) throws -> String? { + guard let data = try getData(key) else { + return nil + } + guard let string = String(data: data, encoding: .utf8) else { + print("failed to convert data to string") + throw Status.conversionError + } + return string + } + + public func getData(_ key: String) throws -> Data? { + var query = options.query() + + query[MatchLimit] = MatchLimitOne + query[ReturnData] = kCFBooleanTrue + + query[AttributeAccount] = key + + var result: AnyObject? + let status = SecItemCopyMatching(query as CFDictionary, &result) + + switch status { + case errSecSuccess: + guard let data = result as? Data else { + throw Status.unexpectedError + } + return data + case errSecItemNotFound: + return nil + default: + throw securityError(status: status) + } + } + + public func get(_ key: String, handler: (Attributes?) -> T) throws -> T { + var query = options.query() + + query[MatchLimit] = MatchLimitOne + + query[ReturnData] = kCFBooleanTrue + query[ReturnAttributes] = kCFBooleanTrue + query[ReturnRef] = kCFBooleanTrue + query[ReturnPersistentRef] = kCFBooleanTrue + + query[AttributeAccount] = key + + var result: AnyObject? + let status = SecItemCopyMatching(query as CFDictionary, &result) + + switch status { + case errSecSuccess: + guard let attributes = result as? [String: Any] else { + throw Status.unexpectedError + } + return handler(Attributes(attributes: attributes)) + case errSecItemNotFound: + return handler(nil) + default: + throw securityError(status: status) + } + } + + // MARK: + + public func set(_ value: String, key: String) throws { + guard let data = value.data(using: .utf8, allowLossyConversion: false) else { + print("failed to convert string to data") + throw Status.conversionError + } + try set(data, key: key) + } + + public func set(_ value: Data, key: String) throws { + var query = options.query() + query[AttributeAccount] = key + #if os(iOS) + if #available(iOS 9.0, *) { + query[UseAuthenticationUI] = UseAuthenticationUIFail + } else { + query[UseNoAuthenticationUI] = kCFBooleanTrue + } + #elseif os(OSX) + query[ReturnData] = kCFBooleanTrue + if #available(OSX 10.11, *) { + query[UseAuthenticationUI] = UseAuthenticationUIFail + } + #endif + + var status = SecItemCopyMatching(query as CFDictionary, nil) + switch status { + case errSecSuccess, errSecInteractionNotAllowed: + var query = options.query() + query[AttributeAccount] = key + + var (attributes, error) = options.attributes(key: nil, value: value) + if let error = error { + print(error.localizedDescription) + throw error + } + + options.attributes.forEach { attributes.updateValue($1, forKey: $0) } + + #if os(iOS) + if status == errSecInteractionNotAllowed && floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_8_0) { + try remove(key) + try set(value, key: key) + } else { + status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary) + if status != errSecSuccess { + throw securityError(status: status) + } + } + #else + status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary) + if status != errSecSuccess { + throw securityError(status: status) + } + #endif + case errSecItemNotFound: + var (attributes, error) = options.attributes(key: key, value: value) + if let error = error { + print(error.localizedDescription) + throw error + } + + options.attributes.forEach { attributes.updateValue($1, forKey: $0) } + + status = SecItemAdd(attributes as CFDictionary, nil) + if status != errSecSuccess { + throw securityError(status: status) + } + default: + throw securityError(status: status) + } + } + + public subscript(key: String) -> String? { + get { + #if swift(>=5.0) + return try? get(key) + #else + return (try? get(key)).flatMap { $0 } + #endif + } + + set { + if let value = newValue { + do { + try set(value, key: key) + } catch {} + } else { + do { + try remove(key) + } catch {} + } + } + } + + public subscript(string key: String) -> String? { + get { + return self[key] + } + + set { + self[key] = newValue + } + } + + public subscript(data key: String) -> Data? { + get { + #if swift(>=5.0) + return try? getData(key) + #else + return (try? getData(key)).flatMap { $0 } + #endif + } + + set { + if let value = newValue { + do { + try set(value, key: key) + } catch {} + } else { + do { + try remove(key) + } catch {} + } + } + } + + public subscript(attributes key: String) -> Attributes? { + get { + #if swift(>=5.0) + return try? get(key) { $0 } + #else + return (try? get(key) { $0 }).flatMap { $0 } + #endif + } + } + + // MARK: + + public func remove(_ key: String) throws { + var query = options.query() + query[AttributeAccount] = key + + let status = SecItemDelete(query as CFDictionary) + if status != errSecSuccess && status != errSecItemNotFound { + throw securityError(status: status) + } + } + + public func removeAll() throws { + var query = options.query() + #if !os(iOS) && !os(watchOS) && !os(tvOS) + query[MatchLimit] = MatchLimitAll + #endif + + let status = SecItemDelete(query as CFDictionary) + if status != errSecSuccess && status != errSecItemNotFound { + throw securityError(status: status) + } + } + + // MARK: + + public func contains(_ key: String) throws -> Bool { + var query = options.query() + query[AttributeAccount] = key + + let status = SecItemCopyMatching(query as CFDictionary, nil) + switch status { + case errSecSuccess: + return true + case errSecItemNotFound: + return false + default: + throw securityError(status: status) + } + } + + // MARK: + + public class func allKeys(_ itemClass: ItemClass) -> [(String, String)] { + var query = [String: Any]() + query[Class] = itemClass.rawValue + query[AttributeSynchronizable] = SynchronizableAny + query[MatchLimit] = MatchLimitAll + query[ReturnAttributes] = kCFBooleanTrue + + var result: AnyObject? + let status = SecItemCopyMatching(query as CFDictionary, &result) + + switch status { + case errSecSuccess: + if let items = result as? [[String: Any]] { + return prettify(itemClass: itemClass, items: items).map { + switch itemClass { + case .genericPassword: + return (($0["service"] ?? "") as! String, ($0["key"] ?? "") as! String) + case .internetPassword: + return (($0["server"] ?? "") as! String, ($0["key"] ?? "") as! String) + } + } + } + case errSecItemNotFound: + return [] + default: () + } + + securityError(status: status) + return [] + } + + public func allKeys() -> [String] { + let allItems = type(of: self).prettify(itemClass: itemClass, items: items()) + let filter: ([String: Any]) -> String? = { $0["key"] as? String } + + #if swift(>=4.1) + return allItems.compactMap(filter) + #else + return allItems.flatMap(filter) + #endif + } + + public class func allItems(_ itemClass: ItemClass) -> [[String: Any]] { + var query = [String: Any]() + query[Class] = itemClass.rawValue + query[MatchLimit] = MatchLimitAll + query[ReturnAttributes] = kCFBooleanTrue + #if os(iOS) || os(watchOS) || os(tvOS) + query[ReturnData] = kCFBooleanTrue + #endif + + var result: AnyObject? + let status = SecItemCopyMatching(query as CFDictionary, &result) + + switch status { + case errSecSuccess: + if let items = result as? [[String: Any]] { + return prettify(itemClass: itemClass, items: items) + } + case errSecItemNotFound: + return [] + default: () + } + + securityError(status: status) + return [] + } + + public func allItems() -> [[String: Any]] { + return type(of: self).prettify(itemClass: itemClass, items: items()) + } + + #if os(iOS) + @available(iOS 8.0, *) + public func getSharedPassword(_ completion: @escaping (_ account: String?, _ password: String?, _ error: Error?) -> () = { account, password, error -> () in }) { + if let domain = server.host { + type(of: self).requestSharedWebCredential(domain: domain, account: nil) { (credentials, error) -> () in + if let credential = credentials.first { + let account = credential["account"] + let password = credential["password"] + completion(account, password, error) + } else { + completion(nil, nil, error) + } + } + } else { + let error = securityError(status: Status.param.rawValue) + completion(nil, nil, error) + } + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + public func getSharedPassword(_ account: String, completion: @escaping (_ password: String?, _ error: Error?) -> () = { password, error -> () in }) { + if let domain = server.host { + type(of: self).requestSharedWebCredential(domain: domain, account: account) { (credentials, error) -> () in + if let credential = credentials.first { + if let password = credential["password"] { + completion(password, error) + } else { + completion(nil, error) + } + } else { + completion(nil, error) + } + } + } else { + let error = securityError(status: Status.param.rawValue) + completion(nil, error) + } + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + public func setSharedPassword(_ password: String, account: String, completion: @escaping (_ error: Error?) -> () = { e -> () in }) { + setSharedPassword(password as String?, account: account, completion: completion) + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + fileprivate func setSharedPassword(_ password: String?, account: String, completion: @escaping (_ error: Error?) -> () = { e -> () in }) { + if let domain = server.host { + SecAddSharedWebCredential(domain as CFString, account as CFString, password as CFString?) { error -> () in + if let error = error { + completion(error.error) + } else { + completion(nil) + } + } + } else { + let error = securityError(status: Status.param.rawValue) + completion(error) + } + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + public func removeSharedPassword(_ account: String, completion: @escaping (_ error: Error?) -> () = { e -> () in }) { + setSharedPassword(nil, account: account, completion: completion) + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + public class func requestSharedWebCredential(_ completion: @escaping (_ credentials: [[String: String]], _ error: Error?) -> () = { credentials, error -> () in }) { + requestSharedWebCredential(domain: nil, account: nil, completion: completion) + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + public class func requestSharedWebCredential(domain: String, completion: @escaping (_ credentials: [[String: String]], _ error: Error?) -> () = { credentials, error -> () in }) { + requestSharedWebCredential(domain: domain, account: nil, completion: completion) + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + public class func requestSharedWebCredential(domain: String, account: String, completion: @escaping (_ credentials: [[String: String]], _ error: Error?) -> () = { credentials, error -> () in }) { + requestSharedWebCredential(domain: Optional(domain), account: Optional(account)!, completion: completion) + } + #endif + + #if os(iOS) + @available(iOS 8.0, *) + fileprivate class func requestSharedWebCredential(domain: String?, account: String?, completion: @escaping (_ credentials: [[String: String]], _ error: Error?) -> ()) { + SecRequestSharedWebCredential(domain as CFString?, account as CFString?) { (credentials, error) -> () in + var remoteError: NSError? + if let error = error { + remoteError = error.error + if remoteError?.code != Int(errSecItemNotFound) { + print("error:[\(remoteError!.code)] \(remoteError!.localizedDescription)") + } + } + if let credentials = credentials { + let credentials = (credentials as NSArray).map { credentials -> [String: String] in + var credential = [String: String]() + if let credentials = credentials as? [String: String] { + if let server = credentials[AttributeServer] { + credential["server"] = server + } + if let account = credentials[AttributeAccount] { + credential["account"] = account + } + if let password = credentials[SharedPassword] { + credential["password"] = password + } + } + return credential + } + completion(credentials, remoteError) + } else { + completion([], remoteError) + } + } + } + #endif + + #if os(iOS) + /** + @abstract Returns a randomly generated password. + @return String password in the form xxx-xxx-xxx-xxx where x is taken from the sets "abcdefghkmnopqrstuvwxy", "ABCDEFGHJKLMNPQRSTUVWXYZ", "3456789" with at least one character from each set being present. + */ + @available(iOS 8.0, *) + public class func generatePassword() -> String { + return SecCreateSharedWebCredentialPassword()! as String + } + #endif + + // MARK: + + fileprivate func items() -> [[String: Any]] { + var query = options.query() + query[MatchLimit] = MatchLimitAll + query[ReturnAttributes] = kCFBooleanTrue + #if os(iOS) || os(watchOS) || os(tvOS) + query[ReturnData] = kCFBooleanTrue + #endif + + var result: AnyObject? + let status = SecItemCopyMatching(query as CFDictionary, &result) + + switch status { + case errSecSuccess: + if let items = result as? [[String: Any]] { + return items + } + case errSecItemNotFound: + return [] + default: () + } + + securityError(status: status) + return [] + } + + fileprivate class func prettify(itemClass: ItemClass, items: [[String: Any]]) -> [[String: Any]] { + let items = items.map { attributes -> [String: Any] in + var item = [String: Any]() + + item["class"] = itemClass.description + + switch itemClass { + case .genericPassword: + if let service = attributes[AttributeService] as? String { + item["service"] = service + } + if let accessGroup = attributes[AttributeAccessGroup] as? String { + item["accessGroup"] = accessGroup + } + case .internetPassword: + if let server = attributes[AttributeServer] as? String { + item["server"] = server + } + if let proto = attributes[AttributeProtocol] as? String { + if let protocolType = ProtocolType(rawValue: proto) { + item["protocol"] = protocolType.description + } + } + if let auth = attributes[AttributeAuthenticationType] as? String { + if let authenticationType = AuthenticationType(rawValue: auth) { + item["authenticationType"] = authenticationType.description + } + } + } + + if let key = attributes[AttributeAccount] as? String { + item["key"] = key + } + if let data = attributes[ValueData] as? Data { + if let text = String(data: data, encoding: .utf8) { + item["value"] = text + } else { + item["value"] = data + } + } + + if let accessible = attributes[AttributeAccessible] as? String { + if let accessibility = Accessibility(rawValue: accessible) { + item["accessibility"] = accessibility.description + } + } + if let synchronizable = attributes[AttributeSynchronizable] as? Bool { + item["synchronizable"] = synchronizable ? "true" : "false" + } + + return item + } + return items + } + + // MARK: + + @discardableResult + fileprivate class func securityError(status: OSStatus) -> Error { + let error = Status(status: status) + print("OSStatus error:[\(error.errorCode)] \(error.description)") + + return error + } + + @discardableResult + fileprivate func securityError(status: OSStatus) -> Error { + return type(of: self).securityError(status: status) + } +} + +struct Options { + var itemClass: ItemClass = .genericPassword + + var service: String = "" + var accessGroup: String? = nil + + var server: URL! + var protocolType: ProtocolType! + var authenticationType: AuthenticationType = .default + + var accessibility: Accessibility = .afterFirstUnlock + var authenticationPolicy: AuthenticationPolicy? + + var synchronizable: Bool = false + + var label: String? + var comment: String? + + var authenticationPrompt: String? + var authenticationContext: AnyObject? + + var attributes = [String: Any]() +} + +/** Class Key Constant */ +private let Class = String(kSecClass) + +/** Attribute Key Constants */ +private let AttributeAccessible = String(kSecAttrAccessible) + +@available(iOS 8.0, OSX 10.10, *) +private let AttributeAccessControl = String(kSecAttrAccessControl) + +private let AttributeAccessGroup = String(kSecAttrAccessGroup) +private let AttributeSynchronizable = String(kSecAttrSynchronizable) +private let AttributeCreationDate = String(kSecAttrCreationDate) +private let AttributeModificationDate = String(kSecAttrModificationDate) +private let AttributeDescription = String(kSecAttrDescription) +private let AttributeComment = String(kSecAttrComment) +private let AttributeCreator = String(kSecAttrCreator) +private let AttributeType = String(kSecAttrType) +private let AttributeLabel = String(kSecAttrLabel) +private let AttributeIsInvisible = String(kSecAttrIsInvisible) +private let AttributeIsNegative = String(kSecAttrIsNegative) +private let AttributeAccount = String(kSecAttrAccount) +private let AttributeService = String(kSecAttrService) +private let AttributeGeneric = String(kSecAttrGeneric) +private let AttributeSecurityDomain = String(kSecAttrSecurityDomain) +private let AttributeServer = String(kSecAttrServer) +private let AttributeProtocol = String(kSecAttrProtocol) +private let AttributeAuthenticationType = String(kSecAttrAuthenticationType) +private let AttributePort = String(kSecAttrPort) +private let AttributePath = String(kSecAttrPath) + +private let SynchronizableAny = kSecAttrSynchronizableAny + +/** Search Constants */ +private let MatchLimit = String(kSecMatchLimit) +private let MatchLimitOne = kSecMatchLimitOne +private let MatchLimitAll = kSecMatchLimitAll + +/** Return Type Key Constants */ +private let ReturnData = String(kSecReturnData) +private let ReturnAttributes = String(kSecReturnAttributes) +private let ReturnRef = String(kSecReturnRef) +private let ReturnPersistentRef = String(kSecReturnPersistentRef) + +/** Value Type Key Constants */ +private let ValueData = String(kSecValueData) +private let ValueRef = String(kSecValueRef) +private let ValuePersistentRef = String(kSecValuePersistentRef) + +/** Other Constants */ +@available(iOS 8.0, OSX 10.10, *) +private let UseOperationPrompt = String(kSecUseOperationPrompt) + +#if os(iOS) +@available(iOS, introduced: 8.0, deprecated: 9.0, message: "Use a UseAuthenticationUI instead.") +private let UseNoAuthenticationUI = String(kSecUseNoAuthenticationUI) +#endif + +@available(iOS 9.0, OSX 10.11, *) +@available(watchOS, unavailable) +private let UseAuthenticationUI = String(kSecUseAuthenticationUI) + +@available(iOS 9.0, OSX 10.11, *) +@available(watchOS, unavailable) +private let UseAuthenticationContext = String(kSecUseAuthenticationContext) + +@available(iOS 9.0, OSX 10.11, *) +@available(watchOS, unavailable) +private let UseAuthenticationUIAllow = String(kSecUseAuthenticationUIAllow) + +@available(iOS 9.0, OSX 10.11, *) +@available(watchOS, unavailable) +private let UseAuthenticationUIFail = String(kSecUseAuthenticationUIFail) + +@available(iOS 9.0, OSX 10.11, *) +@available(watchOS, unavailable) +private let UseAuthenticationUISkip = String(kSecUseAuthenticationUISkip) + +#if os(iOS) +/** Credential Key Constants */ +private let SharedPassword = String(kSecSharedPassword) +#endif + +extension Keychain: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + let items = allItems() + if items.isEmpty { + return "[]" + } + var description = "[\n" + for item in items { + description += " " + description += "\(item)\n" + } + description += "]" + return description + } + + public var debugDescription: String { + return "\(items())" + } +} + +extension Options { + + func query() -> [String: Any] { + var query = [String: Any]() + + query[Class] = itemClass.rawValue + query[AttributeSynchronizable] = SynchronizableAny + + switch itemClass { + case .genericPassword: + query[AttributeService] = service + // Access group is not supported on any simulators. + #if (!arch(i386) && !arch(x86_64)) || (!os(iOS) && !os(watchOS) && !os(tvOS)) + if let accessGroup = self.accessGroup { + query[AttributeAccessGroup] = accessGroup + } + #endif + case .internetPassword: + query[AttributeServer] = server.host + query[AttributePort] = server.port + query[AttributeProtocol] = protocolType.rawValue + query[AttributeAuthenticationType] = authenticationType.rawValue + } + + if #available(OSX 10.10, *) { + if authenticationPrompt != nil { + query[UseOperationPrompt] = authenticationPrompt + } + } + + #if !os(watchOS) + if #available(iOS 9.0, OSX 10.11, *) { + if authenticationContext != nil { + query[UseAuthenticationContext] = authenticationContext + } + } + #endif + + return query + } + + func attributes(key: String?, value: Data) -> ([String: Any], Error?) { + var attributes: [String: Any] + + if key != nil { + attributes = query() + attributes[AttributeAccount] = key + } else { + attributes = [String: Any]() + } + + attributes[ValueData] = value + + if label != nil { + attributes[AttributeLabel] = label + } + if comment != nil { + attributes[AttributeComment] = comment + } + + if let policy = authenticationPolicy { + if #available(OSX 10.10, *) { + var error: Unmanaged? + guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, SecAccessControlCreateFlags(rawValue: CFOptionFlags(policy.rawValue)), &error) else { + if let error = error?.takeUnretainedValue() { + return (attributes, error.error) + } + + return (attributes, Status.unexpectedError) + } + attributes[AttributeAccessControl] = accessControl + } else { + print("Unavailable 'Touch ID integration' on OS X versions prior to 10.10.") + } + } else { + attributes[AttributeAccessible] = accessibility.rawValue + } + + attributes[AttributeSynchronizable] = synchronizable ? kCFBooleanTrue : kCFBooleanFalse + + return (attributes, nil) + } +} + +// MARK: + +extension Attributes: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + return "\(attributes)" + } + + public var debugDescription: String { + return description + } +} + +extension ItemClass: RawRepresentable, CustomStringConvertible { + + public init?(rawValue: String) { + switch rawValue { + case String(kSecClassGenericPassword): + self = .genericPassword + case String(kSecClassInternetPassword): + self = .internetPassword + default: + return nil + } + } + + public var rawValue: String { + switch self { + case .genericPassword: + return String(kSecClassGenericPassword) + case .internetPassword: + return String(kSecClassInternetPassword) + } + } + + public var description: String { + switch self { + case .genericPassword: + return "GenericPassword" + case .internetPassword: + return "InternetPassword" + } + } +} + +extension ProtocolType: RawRepresentable, CustomStringConvertible { + + public init?(rawValue: String) { + switch rawValue { + case String(kSecAttrProtocolFTP): + self = .ftp + case String(kSecAttrProtocolFTPAccount): + self = .ftpAccount + case String(kSecAttrProtocolHTTP): + self = .http + case String(kSecAttrProtocolIRC): + self = .irc + case String(kSecAttrProtocolNNTP): + self = .nntp + case String(kSecAttrProtocolPOP3): + self = .pop3 + case String(kSecAttrProtocolSMTP): + self = .smtp + case String(kSecAttrProtocolSOCKS): + self = .socks + case String(kSecAttrProtocolIMAP): + self = .imap + case String(kSecAttrProtocolLDAP): + self = .ldap + case String(kSecAttrProtocolAppleTalk): + self = .appleTalk + case String(kSecAttrProtocolAFP): + self = .afp + case String(kSecAttrProtocolTelnet): + self = .telnet + case String(kSecAttrProtocolSSH): + self = .ssh + case String(kSecAttrProtocolFTPS): + self = .ftps + case String(kSecAttrProtocolHTTPS): + self = .https + case String(kSecAttrProtocolHTTPProxy): + self = .httpProxy + case String(kSecAttrProtocolHTTPSProxy): + self = .httpsProxy + case String(kSecAttrProtocolFTPProxy): + self = .ftpProxy + case String(kSecAttrProtocolSMB): + self = .smb + case String(kSecAttrProtocolRTSP): + self = .rtsp + case String(kSecAttrProtocolRTSPProxy): + self = .rtspProxy + case String(kSecAttrProtocolDAAP): + self = .daap + case String(kSecAttrProtocolEPPC): + self = .eppc + case String(kSecAttrProtocolIPP): + self = .ipp + case String(kSecAttrProtocolNNTPS): + self = .nntps + case String(kSecAttrProtocolLDAPS): + self = .ldaps + case String(kSecAttrProtocolTelnetS): + self = .telnetS + case String(kSecAttrProtocolIMAPS): + self = .imaps + case String(kSecAttrProtocolIRCS): + self = .ircs + case String(kSecAttrProtocolPOP3S): + self = .pop3S + default: + return nil + } + } + + public var rawValue: String { + switch self { + case .ftp: + return String(kSecAttrProtocolFTP) + case .ftpAccount: + return String(kSecAttrProtocolFTPAccount) + case .http: + return String(kSecAttrProtocolHTTP) + case .irc: + return String(kSecAttrProtocolIRC) + case .nntp: + return String(kSecAttrProtocolNNTP) + case .pop3: + return String(kSecAttrProtocolPOP3) + case .smtp: + return String(kSecAttrProtocolSMTP) + case .socks: + return String(kSecAttrProtocolSOCKS) + case .imap: + return String(kSecAttrProtocolIMAP) + case .ldap: + return String(kSecAttrProtocolLDAP) + case .appleTalk: + return String(kSecAttrProtocolAppleTalk) + case .afp: + return String(kSecAttrProtocolAFP) + case .telnet: + return String(kSecAttrProtocolTelnet) + case .ssh: + return String(kSecAttrProtocolSSH) + case .ftps: + return String(kSecAttrProtocolFTPS) + case .https: + return String(kSecAttrProtocolHTTPS) + case .httpProxy: + return String(kSecAttrProtocolHTTPProxy) + case .httpsProxy: + return String(kSecAttrProtocolHTTPSProxy) + case .ftpProxy: + return String(kSecAttrProtocolFTPProxy) + case .smb: + return String(kSecAttrProtocolSMB) + case .rtsp: + return String(kSecAttrProtocolRTSP) + case .rtspProxy: + return String(kSecAttrProtocolRTSPProxy) + case .daap: + return String(kSecAttrProtocolDAAP) + case .eppc: + return String(kSecAttrProtocolEPPC) + case .ipp: + return String(kSecAttrProtocolIPP) + case .nntps: + return String(kSecAttrProtocolNNTPS) + case .ldaps: + return String(kSecAttrProtocolLDAPS) + case .telnetS: + return String(kSecAttrProtocolTelnetS) + case .imaps: + return String(kSecAttrProtocolIMAPS) + case .ircs: + return String(kSecAttrProtocolIRCS) + case .pop3S: + return String(kSecAttrProtocolPOP3S) + } + } + + public var description: String { + switch self { + case .ftp: + return "FTP" + case .ftpAccount: + return "FTPAccount" + case .http: + return "HTTP" + case .irc: + return "IRC" + case .nntp: + return "NNTP" + case .pop3: + return "POP3" + case .smtp: + return "SMTP" + case .socks: + return "SOCKS" + case .imap: + return "IMAP" + case .ldap: + return "LDAP" + case .appleTalk: + return "AppleTalk" + case .afp: + return "AFP" + case .telnet: + return "Telnet" + case .ssh: + return "SSH" + case .ftps: + return "FTPS" + case .https: + return "HTTPS" + case .httpProxy: + return "HTTPProxy" + case .httpsProxy: + return "HTTPSProxy" + case .ftpProxy: + return "FTPProxy" + case .smb: + return "SMB" + case .rtsp: + return "RTSP" + case .rtspProxy: + return "RTSPProxy" + case .daap: + return "DAAP" + case .eppc: + return "EPPC" + case .ipp: + return "IPP" + case .nntps: + return "NNTPS" + case .ldaps: + return "LDAPS" + case .telnetS: + return "TelnetS" + case .imaps: + return "IMAPS" + case .ircs: + return "IRCS" + case .pop3S: + return "POP3S" + } + } +} + +extension AuthenticationType: RawRepresentable, CustomStringConvertible { + + public init?(rawValue: String) { + switch rawValue { + case String(kSecAttrAuthenticationTypeNTLM): + self = .ntlm + case String(kSecAttrAuthenticationTypeMSN): + self = .msn + case String(kSecAttrAuthenticationTypeDPA): + self = .dpa + case String(kSecAttrAuthenticationTypeRPA): + self = .rpa + case String(kSecAttrAuthenticationTypeHTTPBasic): + self = .httpBasic + case String(kSecAttrAuthenticationTypeHTTPDigest): + self = .httpDigest + case String(kSecAttrAuthenticationTypeHTMLForm): + self = .htmlForm + case String(kSecAttrAuthenticationTypeDefault): + self = .`default` + default: + return nil + } + } + + public var rawValue: String { + switch self { + case .ntlm: + return String(kSecAttrAuthenticationTypeNTLM) + case .msn: + return String(kSecAttrAuthenticationTypeMSN) + case .dpa: + return String(kSecAttrAuthenticationTypeDPA) + case .rpa: + return String(kSecAttrAuthenticationTypeRPA) + case .httpBasic: + return String(kSecAttrAuthenticationTypeHTTPBasic) + case .httpDigest: + return String(kSecAttrAuthenticationTypeHTTPDigest) + case .htmlForm: + return String(kSecAttrAuthenticationTypeHTMLForm) + case .`default`: + return String(kSecAttrAuthenticationTypeDefault) + } + } + + public var description: String { + switch self { + case .ntlm: + return "NTLM" + case .msn: + return "MSN" + case .dpa: + return "DPA" + case .rpa: + return "RPA" + case .httpBasic: + return "HTTPBasic" + case .httpDigest: + return "HTTPDigest" + case .htmlForm: + return "HTMLForm" + case .`default`: + return "Default" + } + } +} + +extension Accessibility: RawRepresentable, CustomStringConvertible { + + public init?(rawValue: String) { + if #available(OSX 10.10, *) { + switch rawValue { + case String(kSecAttrAccessibleWhenUnlocked): + self = .whenUnlocked + case String(kSecAttrAccessibleAfterFirstUnlock): + self = .afterFirstUnlock + case String(kSecAttrAccessibleAlways): + self = .always + case String(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly): + self = .whenPasscodeSetThisDeviceOnly + case String(kSecAttrAccessibleWhenUnlockedThisDeviceOnly): + self = .whenUnlockedThisDeviceOnly + case String(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly): + self = .afterFirstUnlockThisDeviceOnly + case String(kSecAttrAccessibleAlwaysThisDeviceOnly): + self = .alwaysThisDeviceOnly + default: + return nil + } + } else { + switch rawValue { + case String(kSecAttrAccessibleWhenUnlocked): + self = .whenUnlocked + case String(kSecAttrAccessibleAfterFirstUnlock): + self = .afterFirstUnlock + case String(kSecAttrAccessibleAlways): + self = .always + case String(kSecAttrAccessibleWhenUnlockedThisDeviceOnly): + self = .whenUnlockedThisDeviceOnly + case String(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly): + self = .afterFirstUnlockThisDeviceOnly + case String(kSecAttrAccessibleAlwaysThisDeviceOnly): + self = .alwaysThisDeviceOnly + default: + return nil + } + } + } + + public var rawValue: String { + switch self { + case .whenUnlocked: + return String(kSecAttrAccessibleWhenUnlocked) + case .afterFirstUnlock: + return String(kSecAttrAccessibleAfterFirstUnlock) + case .always: + return String(kSecAttrAccessibleAlways) + case .whenPasscodeSetThisDeviceOnly: + if #available(OSX 10.10, *) { + return String(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly) + } else { + fatalError("'Accessibility.WhenPasscodeSetThisDeviceOnly' is not available on this version of OS.") + } + case .whenUnlockedThisDeviceOnly: + return String(kSecAttrAccessibleWhenUnlockedThisDeviceOnly) + case .afterFirstUnlockThisDeviceOnly: + return String(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) + case .alwaysThisDeviceOnly: + return String(kSecAttrAccessibleAlwaysThisDeviceOnly) + } + } + + public var description: String { + switch self { + case .whenUnlocked: + return "WhenUnlocked" + case .afterFirstUnlock: + return "AfterFirstUnlock" + case .always: + return "Always" + case .whenPasscodeSetThisDeviceOnly: + return "WhenPasscodeSetThisDeviceOnly" + case .whenUnlockedThisDeviceOnly: + return "WhenUnlockedThisDeviceOnly" + case .afterFirstUnlockThisDeviceOnly: + return "AfterFirstUnlockThisDeviceOnly" + case .alwaysThisDeviceOnly: + return "AlwaysThisDeviceOnly" + } + } +} + +extension CFError { + var error: NSError { + let domain = CFErrorGetDomain(self) as String + let code = CFErrorGetCode(self) + let userInfo = CFErrorCopyUserInfo(self) as! [String: Any] + + return NSError(domain: domain, code: code, userInfo: userInfo) + } +} + +public enum Status: OSStatus, Error { + case success = 0 + case unimplemented = -4 + case diskFull = -34 + case io = -36 + case opWr = -49 + case param = -50 + case wrPerm = -61 + case allocate = -108 + case userCanceled = -128 + case badReq = -909 + case internalComponent = -2070 + case notAvailable = -25291 + case readOnly = -25292 + case authFailed = -25293 + case noSuchKeychain = -25294 + case invalidKeychain = -25295 + case duplicateKeychain = -25296 + case duplicateCallback = -25297 + case invalidCallback = -25298 + case duplicateItem = -25299 + case itemNotFound = -25300 + case bufferTooSmall = -25301 + case dataTooLarge = -25302 + case noSuchAttr = -25303 + case invalidItemRef = -25304 + case invalidSearchRef = -25305 + case noSuchClass = -25306 + case noDefaultKeychain = -25307 + case interactionNotAllowed = -25308 + case readOnlyAttr = -25309 + case wrongSecVersion = -25310 + case keySizeNotAllowed = -25311 + case noStorageModule = -25312 + case noCertificateModule = -25313 + case noPolicyModule = -25314 + case interactionRequired = -25315 + case dataNotAvailable = -25316 + case dataNotModifiable = -25317 + case createChainFailed = -25318 + case invalidPrefsDomain = -25319 + case inDarkWake = -25320 + case aclNotSimple = -25240 + case policyNotFound = -25241 + case invalidTrustSetting = -25242 + case noAccessForItem = -25243 + case invalidOwnerEdit = -25244 + case trustNotAvailable = -25245 + case unsupportedFormat = -25256 + case unknownFormat = -25257 + case keyIsSensitive = -25258 + case multiplePrivKeys = -25259 + case passphraseRequired = -25260 + case invalidPasswordRef = -25261 + case invalidTrustSettings = -25262 + case noTrustSettings = -25263 + case pkcs12VerifyFailure = -25264 + case invalidCertificate = -26265 + case notSigner = -26267 + case policyDenied = -26270 + case invalidKey = -26274 + case decode = -26275 + case `internal` = -26276 + case unsupportedAlgorithm = -26268 + case unsupportedOperation = -26271 + case unsupportedPadding = -26273 + case itemInvalidKey = -34000 + case itemInvalidKeyType = -34001 + case itemInvalidValue = -34002 + case itemClassMissing = -34003 + case itemMatchUnsupported = -34004 + case useItemListUnsupported = -34005 + case useKeychainUnsupported = -34006 + case useKeychainListUnsupported = -34007 + case returnDataUnsupported = -34008 + case returnAttributesUnsupported = -34009 + case returnRefUnsupported = -34010 + case returnPersitentRefUnsupported = -34011 + case valueRefUnsupported = -34012 + case valuePersistentRefUnsupported = -34013 + case returnMissingPointer = -34014 + case matchLimitUnsupported = -34015 + case itemIllegalQuery = -34016 + case waitForCallback = -34017 + case missingEntitlement = -34018 + case upgradePending = -34019 + case mpSignatureInvalid = -25327 + case otrTooOld = -25328 + case otrIDTooNew = -25329 + case serviceNotAvailable = -67585 + case insufficientClientID = -67586 + case deviceReset = -67587 + case deviceFailed = -67588 + case appleAddAppACLSubject = -67589 + case applePublicKeyIncomplete = -67590 + case appleSignatureMismatch = -67591 + case appleInvalidKeyStartDate = -67592 + case appleInvalidKeyEndDate = -67593 + case conversionError = -67594 + case appleSSLv2Rollback = -67595 + case quotaExceeded = -67596 + case fileTooBig = -67597 + case invalidDatabaseBlob = -67598 + case invalidKeyBlob = -67599 + case incompatibleDatabaseBlob = -67600 + case incompatibleKeyBlob = -67601 + case hostNameMismatch = -67602 + case unknownCriticalExtensionFlag = -67603 + case noBasicConstraints = -67604 + case noBasicConstraintsCA = -67605 + case invalidAuthorityKeyID = -67606 + case invalidSubjectKeyID = -67607 + case invalidKeyUsageForPolicy = -67608 + case invalidExtendedKeyUsage = -67609 + case invalidIDLinkage = -67610 + case pathLengthConstraintExceeded = -67611 + case invalidRoot = -67612 + case crlExpired = -67613 + case crlNotValidYet = -67614 + case crlNotFound = -67615 + case crlServerDown = -67616 + case crlBadURI = -67617 + case unknownCertExtension = -67618 + case unknownCRLExtension = -67619 + case crlNotTrusted = -67620 + case crlPolicyFailed = -67621 + case idpFailure = -67622 + case smimeEmailAddressesNotFound = -67623 + case smimeBadExtendedKeyUsage = -67624 + case smimeBadKeyUsage = -67625 + case smimeKeyUsageNotCritical = -67626 + case smimeNoEmailAddress = -67627 + case smimeSubjAltNameNotCritical = -67628 + case sslBadExtendedKeyUsage = -67629 + case ocspBadResponse = -67630 + case ocspBadRequest = -67631 + case ocspUnavailable = -67632 + case ocspStatusUnrecognized = -67633 + case endOfData = -67634 + case incompleteCertRevocationCheck = -67635 + case networkFailure = -67636 + case ocspNotTrustedToAnchor = -67637 + case recordModified = -67638 + case ocspSignatureError = -67639 + case ocspNoSigner = -67640 + case ocspResponderMalformedReq = -67641 + case ocspResponderInternalError = -67642 + case ocspResponderTryLater = -67643 + case ocspResponderSignatureRequired = -67644 + case ocspResponderUnauthorized = -67645 + case ocspResponseNonceMismatch = -67646 + case codeSigningBadCertChainLength = -67647 + case codeSigningNoBasicConstraints = -67648 + case codeSigningBadPathLengthConstraint = -67649 + case codeSigningNoExtendedKeyUsage = -67650 + case codeSigningDevelopment = -67651 + case resourceSignBadCertChainLength = -67652 + case resourceSignBadExtKeyUsage = -67653 + case trustSettingDeny = -67654 + case invalidSubjectName = -67655 + case unknownQualifiedCertStatement = -67656 + case mobileMeRequestQueued = -67657 + case mobileMeRequestRedirected = -67658 + case mobileMeServerError = -67659 + case mobileMeServerNotAvailable = -67660 + case mobileMeServerAlreadyExists = -67661 + case mobileMeServerServiceErr = -67662 + case mobileMeRequestAlreadyPending = -67663 + case mobileMeNoRequestPending = -67664 + case mobileMeCSRVerifyFailure = -67665 + case mobileMeFailedConsistencyCheck = -67666 + case notInitialized = -67667 + case invalidHandleUsage = -67668 + case pvcReferentNotFound = -67669 + case functionIntegrityFail = -67670 + case internalError = -67671 + case memoryError = -67672 + case invalidData = -67673 + case mdsError = -67674 + case invalidPointer = -67675 + case selfCheckFailed = -67676 + case functionFailed = -67677 + case moduleManifestVerifyFailed = -67678 + case invalidGUID = -67679 + case invalidHandle = -67680 + case invalidDBList = -67681 + case invalidPassthroughID = -67682 + case invalidNetworkAddress = -67683 + case crlAlreadySigned = -67684 + case invalidNumberOfFields = -67685 + case verificationFailure = -67686 + case unknownTag = -67687 + case invalidSignature = -67688 + case invalidName = -67689 + case invalidCertificateRef = -67690 + case invalidCertificateGroup = -67691 + case tagNotFound = -67692 + case invalidQuery = -67693 + case invalidValue = -67694 + case callbackFailed = -67695 + case aclDeleteFailed = -67696 + case aclReplaceFailed = -67697 + case aclAddFailed = -67698 + case aclChangeFailed = -67699 + case invalidAccessCredentials = -67700 + case invalidRecord = -67701 + case invalidACL = -67702 + case invalidSampleValue = -67703 + case incompatibleVersion = -67704 + case privilegeNotGranted = -67705 + case invalidScope = -67706 + case pvcAlreadyConfigured = -67707 + case invalidPVC = -67708 + case emmLoadFailed = -67709 + case emmUnloadFailed = -67710 + case addinLoadFailed = -67711 + case invalidKeyRef = -67712 + case invalidKeyHierarchy = -67713 + case addinUnloadFailed = -67714 + case libraryReferenceNotFound = -67715 + case invalidAddinFunctionTable = -67716 + case invalidServiceMask = -67717 + case moduleNotLoaded = -67718 + case invalidSubServiceID = -67719 + case attributeNotInContext = -67720 + case moduleManagerInitializeFailed = -67721 + case moduleManagerNotFound = -67722 + case eventNotificationCallbackNotFound = -67723 + case inputLengthError = -67724 + case outputLengthError = -67725 + case privilegeNotSupported = -67726 + case deviceError = -67727 + case attachHandleBusy = -67728 + case notLoggedIn = -67729 + case algorithmMismatch = -67730 + case keyUsageIncorrect = -67731 + case keyBlobTypeIncorrect = -67732 + case keyHeaderInconsistent = -67733 + case unsupportedKeyFormat = -67734 + case unsupportedKeySize = -67735 + case invalidKeyUsageMask = -67736 + case unsupportedKeyUsageMask = -67737 + case invalidKeyAttributeMask = -67738 + case unsupportedKeyAttributeMask = -67739 + case invalidKeyLabel = -67740 + case unsupportedKeyLabel = -67741 + case invalidKeyFormat = -67742 + case unsupportedVectorOfBuffers = -67743 + case invalidInputVector = -67744 + case invalidOutputVector = -67745 + case invalidContext = -67746 + case invalidAlgorithm = -67747 + case invalidAttributeKey = -67748 + case missingAttributeKey = -67749 + case invalidAttributeInitVector = -67750 + case missingAttributeInitVector = -67751 + case invalidAttributeSalt = -67752 + case missingAttributeSalt = -67753 + case invalidAttributePadding = -67754 + case missingAttributePadding = -67755 + case invalidAttributeRandom = -67756 + case missingAttributeRandom = -67757 + case invalidAttributeSeed = -67758 + case missingAttributeSeed = -67759 + case invalidAttributePassphrase = -67760 + case missingAttributePassphrase = -67761 + case invalidAttributeKeyLength = -67762 + case missingAttributeKeyLength = -67763 + case invalidAttributeBlockSize = -67764 + case missingAttributeBlockSize = -67765 + case invalidAttributeOutputSize = -67766 + case missingAttributeOutputSize = -67767 + case invalidAttributeRounds = -67768 + case missingAttributeRounds = -67769 + case invalidAlgorithmParms = -67770 + case missingAlgorithmParms = -67771 + case invalidAttributeLabel = -67772 + case missingAttributeLabel = -67773 + case invalidAttributeKeyType = -67774 + case missingAttributeKeyType = -67775 + case invalidAttributeMode = -67776 + case missingAttributeMode = -67777 + case invalidAttributeEffectiveBits = -67778 + case missingAttributeEffectiveBits = -67779 + case invalidAttributeStartDate = -67780 + case missingAttributeStartDate = -67781 + case invalidAttributeEndDate = -67782 + case missingAttributeEndDate = -67783 + case invalidAttributeVersion = -67784 + case missingAttributeVersion = -67785 + case invalidAttributePrime = -67786 + case missingAttributePrime = -67787 + case invalidAttributeBase = -67788 + case missingAttributeBase = -67789 + case invalidAttributeSubprime = -67790 + case missingAttributeSubprime = -67791 + case invalidAttributeIterationCount = -67792 + case missingAttributeIterationCount = -67793 + case invalidAttributeDLDBHandle = -67794 + case missingAttributeDLDBHandle = -67795 + case invalidAttributeAccessCredentials = -67796 + case missingAttributeAccessCredentials = -67797 + case invalidAttributePublicKeyFormat = -67798 + case missingAttributePublicKeyFormat = -67799 + case invalidAttributePrivateKeyFormat = -67800 + case missingAttributePrivateKeyFormat = -67801 + case invalidAttributeSymmetricKeyFormat = -67802 + case missingAttributeSymmetricKeyFormat = -67803 + case invalidAttributeWrappedKeyFormat = -67804 + case missingAttributeWrappedKeyFormat = -67805 + case stagedOperationInProgress = -67806 + case stagedOperationNotStarted = -67807 + case verifyFailed = -67808 + case querySizeUnknown = -67809 + case blockSizeMismatch = -67810 + case publicKeyInconsistent = -67811 + case deviceVerifyFailed = -67812 + case invalidLoginName = -67813 + case alreadyLoggedIn = -67814 + case invalidDigestAlgorithm = -67815 + case invalidCRLGroup = -67816 + case certificateCannotOperate = -67817 + case certificateExpired = -67818 + case certificateNotValidYet = -67819 + case certificateRevoked = -67820 + case certificateSuspended = -67821 + case insufficientCredentials = -67822 + case invalidAction = -67823 + case invalidAuthority = -67824 + case verifyActionFailed = -67825 + case invalidCertAuthority = -67826 + case invaldCRLAuthority = -67827 + case invalidCRLEncoding = -67828 + case invalidCRLType = -67829 + case invalidCRL = -67830 + case invalidFormType = -67831 + case invalidID = -67832 + case invalidIdentifier = -67833 + case invalidIndex = -67834 + case invalidPolicyIdentifiers = -67835 + case invalidTimeString = -67836 + case invalidReason = -67837 + case invalidRequestInputs = -67838 + case invalidResponseVector = -67839 + case invalidStopOnPolicy = -67840 + case invalidTuple = -67841 + case multipleValuesUnsupported = -67842 + case notTrusted = -67843 + case noDefaultAuthority = -67844 + case rejectedForm = -67845 + case requestLost = -67846 + case requestRejected = -67847 + case unsupportedAddressType = -67848 + case unsupportedService = -67849 + case invalidTupleGroup = -67850 + case invalidBaseACLs = -67851 + case invalidTupleCredendtials = -67852 + case invalidEncoding = -67853 + case invalidValidityPeriod = -67854 + case invalidRequestor = -67855 + case requestDescriptor = -67856 + case invalidBundleInfo = -67857 + case invalidCRLIndex = -67858 + case noFieldValues = -67859 + case unsupportedFieldFormat = -67860 + case unsupportedIndexInfo = -67861 + case unsupportedLocality = -67862 + case unsupportedNumAttributes = -67863 + case unsupportedNumIndexes = -67864 + case unsupportedNumRecordTypes = -67865 + case fieldSpecifiedMultiple = -67866 + case incompatibleFieldFormat = -67867 + case invalidParsingModule = -67868 + case databaseLocked = -67869 + case datastoreIsOpen = -67870 + case missingValue = -67871 + case unsupportedQueryLimits = -67872 + case unsupportedNumSelectionPreds = -67873 + case unsupportedOperator = -67874 + case invalidDBLocation = -67875 + case invalidAccessRequest = -67876 + case invalidIndexInfo = -67877 + case invalidNewOwner = -67878 + case invalidModifyMode = -67879 + case missingRequiredExtension = -67880 + case extendedKeyUsageNotCritical = -67881 + case timestampMissing = -67882 + case timestampInvalid = -67883 + case timestampNotTrusted = -67884 + case timestampServiceNotAvailable = -67885 + case timestampBadAlg = -67886 + case timestampBadRequest = -67887 + case timestampBadDataFormat = -67888 + case timestampTimeNotAvailable = -67889 + case timestampUnacceptedPolicy = -67890 + case timestampUnacceptedExtension = -67891 + case timestampAddInfoNotAvailable = -67892 + case timestampSystemFailure = -67893 + case signingTimeMissing = -67894 + case timestampRejection = -67895 + case timestampWaiting = -67896 + case timestampRevocationWarning = -67897 + case timestampRevocationNotification = -67898 + case unexpectedError = -99999 +} + +extension Status: RawRepresentable, CustomStringConvertible { + + public init(status: OSStatus) { + if let mappedStatus = Status(rawValue: status) { + self = mappedStatus + } else { + self = .unexpectedError + } + } + + public var description: String { + switch self { + case .success: + return "No error." + case .unimplemented: + return "Function or operation not implemented." + case .diskFull: + return "The disk is full." + case .io: + return "I/O error (bummers)" + case .opWr: + return "file already open with with write permission" + case .param: + return "One or more parameters passed to a function were not valid." + case .wrPerm: + return "write permissions error" + case .allocate: + return "Failed to allocate memory." + case .userCanceled: + return "User canceled the operation." + case .badReq: + return "Bad parameter or invalid state for operation." + case .internalComponent: + return "" + case .notAvailable: + return "No keychain is available. You may need to restart your computer." + case .readOnly: + return "This keychain cannot be modified." + case .authFailed: + return "The user name or passphrase you entered is not correct." + case .noSuchKeychain: + return "The specified keychain could not be found." + case .invalidKeychain: + return "The specified keychain is not a valid keychain file." + case .duplicateKeychain: + return "A keychain with the same name already exists." + case .duplicateCallback: + return "The specified callback function is already installed." + case .invalidCallback: + return "The specified callback function is not valid." + case .duplicateItem: + return "The specified item already exists in the keychain." + case .itemNotFound: + return "The specified item could not be found in the keychain." + case .bufferTooSmall: + return "There is not enough memory available to use the specified item." + case .dataTooLarge: + return "This item contains information which is too large or in a format that cannot be displayed." + case .noSuchAttr: + return "The specified attribute does not exist." + case .invalidItemRef: + return "The specified item is no longer valid. It may have been deleted from the keychain." + case .invalidSearchRef: + return "Unable to search the current keychain." + case .noSuchClass: + return "The specified item does not appear to be a valid keychain item." + case .noDefaultKeychain: + return "A default keychain could not be found." + case .interactionNotAllowed: + return "User interaction is not allowed." + case .readOnlyAttr: + return "The specified attribute could not be modified." + case .wrongSecVersion: + return "This keychain was created by a different version of the system software and cannot be opened." + case .keySizeNotAllowed: + return "This item specifies a key size which is too large." + case .noStorageModule: + return "A required component (data storage module) could not be loaded. You may need to restart your computer." + case .noCertificateModule: + return "A required component (certificate module) could not be loaded. You may need to restart your computer." + case .noPolicyModule: + return "A required component (policy module) could not be loaded. You may need to restart your computer." + case .interactionRequired: + return "User interaction is required, but is currently not allowed." + case .dataNotAvailable: + return "The contents of this item cannot be retrieved." + case .dataNotModifiable: + return "The contents of this item cannot be modified." + case .createChainFailed: + return "One or more certificates required to validate this certificate cannot be found." + case .invalidPrefsDomain: + return "The specified preferences domain is not valid." + case .inDarkWake: + return "In dark wake, no UI possible" + case .aclNotSimple: + return "The specified access control list is not in standard (simple) form." + case .policyNotFound: + return "The specified policy cannot be found." + case .invalidTrustSetting: + return "The specified trust setting is invalid." + case .noAccessForItem: + return "The specified item has no access control." + case .invalidOwnerEdit: + return "Invalid attempt to change the owner of this item." + case .trustNotAvailable: + return "No trust results are available." + case .unsupportedFormat: + return "Import/Export format unsupported." + case .unknownFormat: + return "Unknown format in import." + case .keyIsSensitive: + return "Key material must be wrapped for export." + case .multiplePrivKeys: + return "An attempt was made to import multiple private keys." + case .passphraseRequired: + return "Passphrase is required for import/export." + case .invalidPasswordRef: + return "The password reference was invalid." + case .invalidTrustSettings: + return "The Trust Settings Record was corrupted." + case .noTrustSettings: + return "No Trust Settings were found." + case .pkcs12VerifyFailure: + return "MAC verification failed during PKCS12 import (wrong password?)" + case .invalidCertificate: + return "This certificate could not be decoded." + case .notSigner: + return "A certificate was not signed by its proposed parent." + case .policyDenied: + return "The certificate chain was not trusted due to a policy not accepting it." + case .invalidKey: + return "The provided key material was not valid." + case .decode: + return "Unable to decode the provided data." + case .`internal`: + return "An internal error occurred in the Security framework." + case .unsupportedAlgorithm: + return "An unsupported algorithm was encountered." + case .unsupportedOperation: + return "The operation you requested is not supported by this key." + case .unsupportedPadding: + return "The padding you requested is not supported." + case .itemInvalidKey: + return "A string key in dictionary is not one of the supported keys." + case .itemInvalidKeyType: + return "A key in a dictionary is neither a CFStringRef nor a CFNumberRef." + case .itemInvalidValue: + return "A value in a dictionary is an invalid (or unsupported) CF type." + case .itemClassMissing: + return "No kSecItemClass key was specified in a dictionary." + case .itemMatchUnsupported: + return "The caller passed one or more kSecMatch keys to a function which does not support matches." + case .useItemListUnsupported: + return "The caller passed in a kSecUseItemList key to a function which does not support it." + case .useKeychainUnsupported: + return "The caller passed in a kSecUseKeychain key to a function which does not support it." + case .useKeychainListUnsupported: + return "The caller passed in a kSecUseKeychainList key to a function which does not support it." + case .returnDataUnsupported: + return "The caller passed in a kSecReturnData key to a function which does not support it." + case .returnAttributesUnsupported: + return "The caller passed in a kSecReturnAttributes key to a function which does not support it." + case .returnRefUnsupported: + return "The caller passed in a kSecReturnRef key to a function which does not support it." + case .returnPersitentRefUnsupported: + return "The caller passed in a kSecReturnPersistentRef key to a function which does not support it." + case .valueRefUnsupported: + return "The caller passed in a kSecValueRef key to a function which does not support it." + case .valuePersistentRefUnsupported: + return "The caller passed in a kSecValuePersistentRef key to a function which does not support it." + case .returnMissingPointer: + return "The caller passed asked for something to be returned but did not pass in a result pointer." + case .matchLimitUnsupported: + return "The caller passed in a kSecMatchLimit key to a call which does not support limits." + case .itemIllegalQuery: + return "The caller passed in a query which contained too many keys." + case .waitForCallback: + return "This operation is incomplete, until the callback is invoked (not an error)." + case .missingEntitlement: + return "Internal error when a required entitlement isn't present, client has neither application-identifier nor keychain-access-groups entitlements." + case .upgradePending: + return "Error returned if keychain database needs a schema migration but the device is locked, clients should wait for a device unlock notification and retry the command." + case .mpSignatureInvalid: + return "Signature invalid on MP message" + case .otrTooOld: + return "Message is too old to use" + case .otrIDTooNew: + return "Key ID is too new to use! Message from the future?" + case .serviceNotAvailable: + return "The required service is not available." + case .insufficientClientID: + return "The client ID is not correct." + case .deviceReset: + return "A device reset has occurred." + case .deviceFailed: + return "A device failure has occurred." + case .appleAddAppACLSubject: + return "Adding an application ACL subject failed." + case .applePublicKeyIncomplete: + return "The public key is incomplete." + case .appleSignatureMismatch: + return "A signature mismatch has occurred." + case .appleInvalidKeyStartDate: + return "The specified key has an invalid start date." + case .appleInvalidKeyEndDate: + return "The specified key has an invalid end date." + case .conversionError: + return "A conversion error has occurred." + case .appleSSLv2Rollback: + return "A SSLv2 rollback error has occurred." + case .quotaExceeded: + return "The quota was exceeded." + case .fileTooBig: + return "The file is too big." + case .invalidDatabaseBlob: + return "The specified database has an invalid blob." + case .invalidKeyBlob: + return "The specified database has an invalid key blob." + case .incompatibleDatabaseBlob: + return "The specified database has an incompatible blob." + case .incompatibleKeyBlob: + return "The specified database has an incompatible key blob." + case .hostNameMismatch: + return "A host name mismatch has occurred." + case .unknownCriticalExtensionFlag: + return "There is an unknown critical extension flag." + case .noBasicConstraints: + return "No basic constraints were found." + case .noBasicConstraintsCA: + return "No basic CA constraints were found." + case .invalidAuthorityKeyID: + return "The authority key ID is not valid." + case .invalidSubjectKeyID: + return "The subject key ID is not valid." + case .invalidKeyUsageForPolicy: + return "The key usage is not valid for the specified policy." + case .invalidExtendedKeyUsage: + return "The extended key usage is not valid." + case .invalidIDLinkage: + return "The ID linkage is not valid." + case .pathLengthConstraintExceeded: + return "The path length constraint was exceeded." + case .invalidRoot: + return "The root or anchor certificate is not valid." + case .crlExpired: + return "The CRL has expired." + case .crlNotValidYet: + return "The CRL is not yet valid." + case .crlNotFound: + return "The CRL was not found." + case .crlServerDown: + return "The CRL server is down." + case .crlBadURI: + return "The CRL has a bad Uniform Resource Identifier." + case .unknownCertExtension: + return "An unknown certificate extension was encountered." + case .unknownCRLExtension: + return "An unknown CRL extension was encountered." + case .crlNotTrusted: + return "The CRL is not trusted." + case .crlPolicyFailed: + return "The CRL policy failed." + case .idpFailure: + return "The issuing distribution point was not valid." + case .smimeEmailAddressesNotFound: + return "An email address mismatch was encountered." + case .smimeBadExtendedKeyUsage: + return "The appropriate extended key usage for SMIME was not found." + case .smimeBadKeyUsage: + return "The key usage is not compatible with SMIME." + case .smimeKeyUsageNotCritical: + return "The key usage extension is not marked as critical." + case .smimeNoEmailAddress: + return "No email address was found in the certificate." + case .smimeSubjAltNameNotCritical: + return "The subject alternative name extension is not marked as critical." + case .sslBadExtendedKeyUsage: + return "The appropriate extended key usage for SSL was not found." + case .ocspBadResponse: + return "The OCSP response was incorrect or could not be parsed." + case .ocspBadRequest: + return "The OCSP request was incorrect or could not be parsed." + case .ocspUnavailable: + return "OCSP service is unavailable." + case .ocspStatusUnrecognized: + return "The OCSP server did not recognize this certificate." + case .endOfData: + return "An end-of-data was detected." + case .incompleteCertRevocationCheck: + return "An incomplete certificate revocation check occurred." + case .networkFailure: + return "A network failure occurred." + case .ocspNotTrustedToAnchor: + return "The OCSP response was not trusted to a root or anchor certificate." + case .recordModified: + return "The record was modified." + case .ocspSignatureError: + return "The OCSP response had an invalid signature." + case .ocspNoSigner: + return "The OCSP response had no signer." + case .ocspResponderMalformedReq: + return "The OCSP responder was given a malformed request." + case .ocspResponderInternalError: + return "The OCSP responder encountered an internal error." + case .ocspResponderTryLater: + return "The OCSP responder is busy, try again later." + case .ocspResponderSignatureRequired: + return "The OCSP responder requires a signature." + case .ocspResponderUnauthorized: + return "The OCSP responder rejected this request as unauthorized." + case .ocspResponseNonceMismatch: + return "The OCSP response nonce did not match the request." + case .codeSigningBadCertChainLength: + return "Code signing encountered an incorrect certificate chain length." + case .codeSigningNoBasicConstraints: + return "Code signing found no basic constraints." + case .codeSigningBadPathLengthConstraint: + return "Code signing encountered an incorrect path length constraint." + case .codeSigningNoExtendedKeyUsage: + return "Code signing found no extended key usage." + case .codeSigningDevelopment: + return "Code signing indicated use of a development-only certificate." + case .resourceSignBadCertChainLength: + return "Resource signing has encountered an incorrect certificate chain length." + case .resourceSignBadExtKeyUsage: + return "Resource signing has encountered an error in the extended key usage." + case .trustSettingDeny: + return "The trust setting for this policy was set to Deny." + case .invalidSubjectName: + return "An invalid certificate subject name was encountered." + case .unknownQualifiedCertStatement: + return "An unknown qualified certificate statement was encountered." + case .mobileMeRequestQueued: + return "The MobileMe request will be sent during the next connection." + case .mobileMeRequestRedirected: + return "The MobileMe request was redirected." + case .mobileMeServerError: + return "A MobileMe server error occurred." + case .mobileMeServerNotAvailable: + return "The MobileMe server is not available." + case .mobileMeServerAlreadyExists: + return "The MobileMe server reported that the item already exists." + case .mobileMeServerServiceErr: + return "A MobileMe service error has occurred." + case .mobileMeRequestAlreadyPending: + return "A MobileMe request is already pending." + case .mobileMeNoRequestPending: + return "MobileMe has no request pending." + case .mobileMeCSRVerifyFailure: + return "A MobileMe CSR verification failure has occurred." + case .mobileMeFailedConsistencyCheck: + return "MobileMe has found a failed consistency check." + case .notInitialized: + return "A function was called without initializing CSSM." + case .invalidHandleUsage: + return "The CSSM handle does not match with the service type." + case .pvcReferentNotFound: + return "A reference to the calling module was not found in the list of authorized callers." + case .functionIntegrityFail: + return "A function address was not within the verified module." + case .internalError: + return "An internal error has occurred." + case .memoryError: + return "A memory error has occurred." + case .invalidData: + return "Invalid data was encountered." + case .mdsError: + return "A Module Directory Service error has occurred." + case .invalidPointer: + return "An invalid pointer was encountered." + case .selfCheckFailed: + return "Self-check has failed." + case .functionFailed: + return "A function has failed." + case .moduleManifestVerifyFailed: + return "A module manifest verification failure has occurred." + case .invalidGUID: + return "An invalid GUID was encountered." + case .invalidHandle: + return "An invalid handle was encountered." + case .invalidDBList: + return "An invalid DB list was encountered." + case .invalidPassthroughID: + return "An invalid passthrough ID was encountered." + case .invalidNetworkAddress: + return "An invalid network address was encountered." + case .crlAlreadySigned: + return "The certificate revocation list is already signed." + case .invalidNumberOfFields: + return "An invalid number of fields were encountered." + case .verificationFailure: + return "A verification failure occurred." + case .unknownTag: + return "An unknown tag was encountered." + case .invalidSignature: + return "An invalid signature was encountered." + case .invalidName: + return "An invalid name was encountered." + case .invalidCertificateRef: + return "An invalid certificate reference was encountered." + case .invalidCertificateGroup: + return "An invalid certificate group was encountered." + case .tagNotFound: + return "The specified tag was not found." + case .invalidQuery: + return "The specified query was not valid." + case .invalidValue: + return "An invalid value was detected." + case .callbackFailed: + return "A callback has failed." + case .aclDeleteFailed: + return "An ACL delete operation has failed." + case .aclReplaceFailed: + return "An ACL replace operation has failed." + case .aclAddFailed: + return "An ACL add operation has failed." + case .aclChangeFailed: + return "An ACL change operation has failed." + case .invalidAccessCredentials: + return "Invalid access credentials were encountered." + case .invalidRecord: + return "An invalid record was encountered." + case .invalidACL: + return "An invalid ACL was encountered." + case .invalidSampleValue: + return "An invalid sample value was encountered." + case .incompatibleVersion: + return "An incompatible version was encountered." + case .privilegeNotGranted: + return "The privilege was not granted." + case .invalidScope: + return "An invalid scope was encountered." + case .pvcAlreadyConfigured: + return "The PVC is already configured." + case .invalidPVC: + return "An invalid PVC was encountered." + case .emmLoadFailed: + return "The EMM load has failed." + case .emmUnloadFailed: + return "The EMM unload has failed." + case .addinLoadFailed: + return "The add-in load operation has failed." + case .invalidKeyRef: + return "An invalid key was encountered." + case .invalidKeyHierarchy: + return "An invalid key hierarchy was encountered." + case .addinUnloadFailed: + return "The add-in unload operation has failed." + case .libraryReferenceNotFound: + return "A library reference was not found." + case .invalidAddinFunctionTable: + return "An invalid add-in function table was encountered." + case .invalidServiceMask: + return "An invalid service mask was encountered." + case .moduleNotLoaded: + return "A module was not loaded." + case .invalidSubServiceID: + return "An invalid subservice ID was encountered." + case .attributeNotInContext: + return "An attribute was not in the context." + case .moduleManagerInitializeFailed: + return "A module failed to initialize." + case .moduleManagerNotFound: + return "A module was not found." + case .eventNotificationCallbackNotFound: + return "An event notification callback was not found." + case .inputLengthError: + return "An input length error was encountered." + case .outputLengthError: + return "An output length error was encountered." + case .privilegeNotSupported: + return "The privilege is not supported." + case .deviceError: + return "A device error was encountered." + case .attachHandleBusy: + return "The CSP handle was busy." + case .notLoggedIn: + return "You are not logged in." + case .algorithmMismatch: + return "An algorithm mismatch was encountered." + case .keyUsageIncorrect: + return "The key usage is incorrect." + case .keyBlobTypeIncorrect: + return "The key blob type is incorrect." + case .keyHeaderInconsistent: + return "The key header is inconsistent." + case .unsupportedKeyFormat: + return "The key header format is not supported." + case .unsupportedKeySize: + return "The key size is not supported." + case .invalidKeyUsageMask: + return "The key usage mask is not valid." + case .unsupportedKeyUsageMask: + return "The key usage mask is not supported." + case .invalidKeyAttributeMask: + return "The key attribute mask is not valid." + case .unsupportedKeyAttributeMask: + return "The key attribute mask is not supported." + case .invalidKeyLabel: + return "The key label is not valid." + case .unsupportedKeyLabel: + return "The key label is not supported." + case .invalidKeyFormat: + return "The key format is not valid." + case .unsupportedVectorOfBuffers: + return "The vector of buffers is not supported." + case .invalidInputVector: + return "The input vector is not valid." + case .invalidOutputVector: + return "The output vector is not valid." + case .invalidContext: + return "An invalid context was encountered." + case .invalidAlgorithm: + return "An invalid algorithm was encountered." + case .invalidAttributeKey: + return "A key attribute was not valid." + case .missingAttributeKey: + return "A key attribute was missing." + case .invalidAttributeInitVector: + return "An init vector attribute was not valid." + case .missingAttributeInitVector: + return "An init vector attribute was missing." + case .invalidAttributeSalt: + return "A salt attribute was not valid." + case .missingAttributeSalt: + return "A salt attribute was missing." + case .invalidAttributePadding: + return "A padding attribute was not valid." + case .missingAttributePadding: + return "A padding attribute was missing." + case .invalidAttributeRandom: + return "A random number attribute was not valid." + case .missingAttributeRandom: + return "A random number attribute was missing." + case .invalidAttributeSeed: + return "A seed attribute was not valid." + case .missingAttributeSeed: + return "A seed attribute was missing." + case .invalidAttributePassphrase: + return "A passphrase attribute was not valid." + case .missingAttributePassphrase: + return "A passphrase attribute was missing." + case .invalidAttributeKeyLength: + return "A key length attribute was not valid." + case .missingAttributeKeyLength: + return "A key length attribute was missing." + case .invalidAttributeBlockSize: + return "A block size attribute was not valid." + case .missingAttributeBlockSize: + return "A block size attribute was missing." + case .invalidAttributeOutputSize: + return "An output size attribute was not valid." + case .missingAttributeOutputSize: + return "An output size attribute was missing." + case .invalidAttributeRounds: + return "The number of rounds attribute was not valid." + case .missingAttributeRounds: + return "The number of rounds attribute was missing." + case .invalidAlgorithmParms: + return "An algorithm parameters attribute was not valid." + case .missingAlgorithmParms: + return "An algorithm parameters attribute was missing." + case .invalidAttributeLabel: + return "A label attribute was not valid." + case .missingAttributeLabel: + return "A label attribute was missing." + case .invalidAttributeKeyType: + return "A key type attribute was not valid." + case .missingAttributeKeyType: + return "A key type attribute was missing." + case .invalidAttributeMode: + return "A mode attribute was not valid." + case .missingAttributeMode: + return "A mode attribute was missing." + case .invalidAttributeEffectiveBits: + return "An effective bits attribute was not valid." + case .missingAttributeEffectiveBits: + return "An effective bits attribute was missing." + case .invalidAttributeStartDate: + return "A start date attribute was not valid." + case .missingAttributeStartDate: + return "A start date attribute was missing." + case .invalidAttributeEndDate: + return "An end date attribute was not valid." + case .missingAttributeEndDate: + return "An end date attribute was missing." + case .invalidAttributeVersion: + return "A version attribute was not valid." + case .missingAttributeVersion: + return "A version attribute was missing." + case .invalidAttributePrime: + return "A prime attribute was not valid." + case .missingAttributePrime: + return "A prime attribute was missing." + case .invalidAttributeBase: + return "A base attribute was not valid." + case .missingAttributeBase: + return "A base attribute was missing." + case .invalidAttributeSubprime: + return "A subprime attribute was not valid." + case .missingAttributeSubprime: + return "A subprime attribute was missing." + case .invalidAttributeIterationCount: + return "An iteration count attribute was not valid." + case .missingAttributeIterationCount: + return "An iteration count attribute was missing." + case .invalidAttributeDLDBHandle: + return "A database handle attribute was not valid." + case .missingAttributeDLDBHandle: + return "A database handle attribute was missing." + case .invalidAttributeAccessCredentials: + return "An access credentials attribute was not valid." + case .missingAttributeAccessCredentials: + return "An access credentials attribute was missing." + case .invalidAttributePublicKeyFormat: + return "A public key format attribute was not valid." + case .missingAttributePublicKeyFormat: + return "A public key format attribute was missing." + case .invalidAttributePrivateKeyFormat: + return "A private key format attribute was not valid." + case .missingAttributePrivateKeyFormat: + return "A private key format attribute was missing." + case .invalidAttributeSymmetricKeyFormat: + return "A symmetric key format attribute was not valid." + case .missingAttributeSymmetricKeyFormat: + return "A symmetric key format attribute was missing." + case .invalidAttributeWrappedKeyFormat: + return "A wrapped key format attribute was not valid." + case .missingAttributeWrappedKeyFormat: + return "A wrapped key format attribute was missing." + case .stagedOperationInProgress: + return "A staged operation is in progress." + case .stagedOperationNotStarted: + return "A staged operation was not started." + case .verifyFailed: + return "A cryptographic verification failure has occurred." + case .querySizeUnknown: + return "The query size is unknown." + case .blockSizeMismatch: + return "A block size mismatch occurred." + case .publicKeyInconsistent: + return "The public key was inconsistent." + case .deviceVerifyFailed: + return "A device verification failure has occurred." + case .invalidLoginName: + return "An invalid login name was detected." + case .alreadyLoggedIn: + return "The user is already logged in." + case .invalidDigestAlgorithm: + return "An invalid digest algorithm was detected." + case .invalidCRLGroup: + return "An invalid CRL group was detected." + case .certificateCannotOperate: + return "The certificate cannot operate." + case .certificateExpired: + return "An expired certificate was detected." + case .certificateNotValidYet: + return "The certificate is not yet valid." + case .certificateRevoked: + return "The certificate was revoked." + case .certificateSuspended: + return "The certificate was suspended." + case .insufficientCredentials: + return "Insufficient credentials were detected." + case .invalidAction: + return "The action was not valid." + case .invalidAuthority: + return "The authority was not valid." + case .verifyActionFailed: + return "A verify action has failed." + case .invalidCertAuthority: + return "The certificate authority was not valid." + case .invaldCRLAuthority: + return "The CRL authority was not valid." + case .invalidCRLEncoding: + return "The CRL encoding was not valid." + case .invalidCRLType: + return "The CRL type was not valid." + case .invalidCRL: + return "The CRL was not valid." + case .invalidFormType: + return "The form type was not valid." + case .invalidID: + return "The ID was not valid." + case .invalidIdentifier: + return "The identifier was not valid." + case .invalidIndex: + return "The index was not valid." + case .invalidPolicyIdentifiers: + return "The policy identifiers are not valid." + case .invalidTimeString: + return "The time specified was not valid." + case .invalidReason: + return "The trust policy reason was not valid." + case .invalidRequestInputs: + return "The request inputs are not valid." + case .invalidResponseVector: + return "The response vector was not valid." + case .invalidStopOnPolicy: + return "The stop-on policy was not valid." + case .invalidTuple: + return "The tuple was not valid." + case .multipleValuesUnsupported: + return "Multiple values are not supported." + case .notTrusted: + return "The trust policy was not trusted." + case .noDefaultAuthority: + return "No default authority was detected." + case .rejectedForm: + return "The trust policy had a rejected form." + case .requestLost: + return "The request was lost." + case .requestRejected: + return "The request was rejected." + case .unsupportedAddressType: + return "The address type is not supported." + case .unsupportedService: + return "The service is not supported." + case .invalidTupleGroup: + return "The tuple group was not valid." + case .invalidBaseACLs: + return "The base ACLs are not valid." + case .invalidTupleCredendtials: + return "The tuple credentials are not valid." + case .invalidEncoding: + return "The encoding was not valid." + case .invalidValidityPeriod: + return "The validity period was not valid." + case .invalidRequestor: + return "The requestor was not valid." + case .requestDescriptor: + return "The request descriptor was not valid." + case .invalidBundleInfo: + return "The bundle information was not valid." + case .invalidCRLIndex: + return "The CRL index was not valid." + case .noFieldValues: + return "No field values were detected." + case .unsupportedFieldFormat: + return "The field format is not supported." + case .unsupportedIndexInfo: + return "The index information is not supported." + case .unsupportedLocality: + return "The locality is not supported." + case .unsupportedNumAttributes: + return "The number of attributes is not supported." + case .unsupportedNumIndexes: + return "The number of indexes is not supported." + case .unsupportedNumRecordTypes: + return "The number of record types is not supported." + case .fieldSpecifiedMultiple: + return "Too many fields were specified." + case .incompatibleFieldFormat: + return "The field format was incompatible." + case .invalidParsingModule: + return "The parsing module was not valid." + case .databaseLocked: + return "The database is locked." + case .datastoreIsOpen: + return "The data store is open." + case .missingValue: + return "A missing value was detected." + case .unsupportedQueryLimits: + return "The query limits are not supported." + case .unsupportedNumSelectionPreds: + return "The number of selection predicates is not supported." + case .unsupportedOperator: + return "The operator is not supported." + case .invalidDBLocation: + return "The database location is not valid." + case .invalidAccessRequest: + return "The access request is not valid." + case .invalidIndexInfo: + return "The index information is not valid." + case .invalidNewOwner: + return "The new owner is not valid." + case .invalidModifyMode: + return "The modify mode is not valid." + case .missingRequiredExtension: + return "A required certificate extension is missing." + case .extendedKeyUsageNotCritical: + return "The extended key usage extension was not marked critical." + case .timestampMissing: + return "A timestamp was expected but was not found." + case .timestampInvalid: + return "The timestamp was not valid." + case .timestampNotTrusted: + return "The timestamp was not trusted." + case .timestampServiceNotAvailable: + return "The timestamp service is not available." + case .timestampBadAlg: + return "An unrecognized or unsupported Algorithm Identifier in timestamp." + case .timestampBadRequest: + return "The timestamp transaction is not permitted or supported." + case .timestampBadDataFormat: + return "The timestamp data submitted has the wrong format." + case .timestampTimeNotAvailable: + return "The time source for the Timestamp Authority is not available." + case .timestampUnacceptedPolicy: + return "The requested policy is not supported by the Timestamp Authority." + case .timestampUnacceptedExtension: + return "The requested extension is not supported by the Timestamp Authority." + case .timestampAddInfoNotAvailable: + return "The additional information requested is not available." + case .timestampSystemFailure: + return "The timestamp request cannot be handled due to system failure." + case .signingTimeMissing: + return "A signing time was expected but was not found." + case .timestampRejection: + return "A timestamp transaction was rejected." + case .timestampWaiting: + return "A timestamp transaction is waiting." + case .timestampRevocationWarning: + return "A timestamp authority revocation warning was issued." + case .timestampRevocationNotification: + return "A timestamp authority revocation notification was issued." + case .unexpectedError: + return "Unexpected error has occurred." + } + } +} + +extension Status: CustomNSError { + public static let errorDomain = KeychainAccessErrorDomain + + public var errorCode: Int { + return Int(rawValue) + } + + public var errorUserInfo: [String : Any] { + return [NSLocalizedDescriptionKey: description] + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/README.md new file mode 100644 index 0000000..838ef2c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/KeychainAccess/README.md @@ -0,0 +1,602 @@ +# KeychainAccess +[![CI Status](http://img.shields.io/travis/kishikawakatsumi/KeychainAccess.svg)](https://travis-ci.org/kishikawakatsumi/KeychainAccess) +[![codecov](https://codecov.io/gh/kishikawakatsumi/KeychainAccess/branch/master/graph/badge.svg)](https://codecov.io/gh/kishikawakatsumi/KeychainAccess) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Version](https://img.shields.io/cocoapods/v/KeychainAccess.svg)](http://cocoadocs.org/docsets/KeychainAccess) +[![Platform](https://img.shields.io/cocoapods/p/KeychainAccess.svg)](http://cocoadocs.org/docsets/KeychainAccess) +[![Swift 3.x](https://img.shields.io/badge/Swift-3.x-orange.svg?style=flat)](https://swift.org/) +[![Swift 4.0](https://img.shields.io/badge/Swift-4.0-orange.svg?style=flat)](https://swift.org/) +[![Swift 4.1](https://img.shields.io/badge/Swift-4.1-orange.svg?style=flat)](https://swift.org/) +[![Swift 4.2](https://img.shields.io/badge/Swift-4.2-orange.svg?style=flat)](https://swift.org/) + +KeychainAccess is a simple Swift wrapper for Keychain that works on iOS and OS X. Makes using Keychain APIs extremely easy and much more palatable to use in Swift. + + + + + +## :bulb: Features + +- Simple interface +- Support access group +- [Support accessibility](#accessibility) +- [Support iCloud sharing](#icloud_sharing) +- **[Support TouchID and Keychain integration (iOS 8+)](#touch_id_integration)** +- **[Support Shared Web Credentials (iOS 8+)](#shared_web_credentials)** +- [Works on both iOS & OS X](#requirements) +- [watchOS and tvOS are supported](#requirements) +- **[Swift 4 & Swift 3 compatible](#requirements)** + +## :book: Usage + +##### :eyes: See also: +- [:link: iOS Example Project](https://github.com/kishikawakatsumi/KeychainAccess/tree/master/Examples/Example-iOS) + +### :key: Basics + +#### Saving Application Password + +```swift +let keychain = Keychain(service: "com.example.github-token") +keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +#### Saving Internet Password + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https) +keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +### :key: Instantiation + +#### Create Keychain for Application Password + +```swift +let keychain = Keychain(service: "com.example.github-token") +``` + +```swift +let keychain = Keychain(service: "com.example.github-token", accessGroup: "12ABCD3E4F.shared") +``` + +#### Create Keychain for Internet Password + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https) +``` + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https, authenticationType: .htmlForm) +``` + +### :key: Adding an item + +#### subscripting + +##### for String + +```swift +keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +```swift +keychain[string: "kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +##### for NSData + +```swift +keychain[data: "secret"] = NSData(contentsOfFile: "secret.bin") +``` + +#### set method + +```swift +keychain.set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") +``` + +#### error handling + +```swift +do { + try keychain.set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") +} +catch let error { + print(error) +} +``` + +### :key: Obtaining an item + +#### subscripting + +##### for String (If the value is NSData, attempt to convert to String) + +```swift +let token = keychain["kishikawakatsumi"] +``` + +```swift +let token = keychain[string: "kishikawakatsumi"] +``` + +##### for NSData + +```swift +let secretData = keychain[data: "secret"] +``` + +#### get methods + +##### as String + +```swift +let token = try? keychain.get("kishikawakatsumi") +``` + +```swift +let token = try? keychain.getString("kishikawakatsumi") +``` + +##### as NSData + +```swift +let data = try? keychain.getData("kishikawakatsumi") +``` + +### :key: Removing an item + +#### subscripting + +```swift +keychain["kishikawakatsumi"] = nil +``` + +#### remove method + +```swift +do { + try keychain.remove("kishikawakatsumi") +} catch let error { + print("error: \(error)") +} +``` + +### :key: Set Label and Comment + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https) +do { + try keychain + .label("github.com (kishikawakatsumi)") + .comment("github access token") + .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") +} catch let error { + print("error: \(error)") +} +``` + +### :key: Obtaining Other Attributes + +#### PersistentRef + +```swift +let keychain = Keychain() +let persistentRef = keychain[attributes: "kishikawakatsumi"].persistentRef +... +``` + +#### Creation Date + +```swift +let keychain = Keychain() +let creationDate = keychain[attributes: "kishikawakatsumi"].creationDate +... +``` + +#### All Attributes + +```swift +let keychain = Keychain() +do { + let attributes = try keychain.get("kishikawakatsumi") { $0 } + print(attributes.comment) + print(attributes.label) + print(attributes.creator) + ... +} catch let error { + print("error: \(error)") +} +``` + +##### subscripting + +```swift +let keychain = Keychain() +let attributes = keychain[attributes: "kishikawakatsumi"] +print(attributes.comment) +print(attributes.label) +print(attributes.creator) +``` + +### :key: Configuration (Accessibility, Sharing, iCloud Sync) + +**Provides fluent interfaces** + +```swift +let keychain = Keychain(service: "com.example.github-token") + .label("github.com (kishikawakatsumi)") + .synchronizable(true) + .accessibility(.afterFirstUnlock) +``` + +#### Accessibility + +##### Default accessibility matches background application (=kSecAttrAccessibleAfterFirstUnlock) + +```swift +let keychain = Keychain(service: "com.example.github-token") +``` + +##### For background application + +###### Creating instance + +```swift +let keychain = Keychain(service: "com.example.github-token") + .accessibility(.afterFirstUnlock) + +keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +###### One-shot + +```swift +let keychain = Keychain(service: "com.example.github-token") + +do { + try keychain + .accessibility(.afterFirstUnlock) + .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") +} catch let error { + print("error: \(error)") +} +``` + +##### For foreground application + +###### Creating instance + +```swift +let keychain = Keychain(service: "com.example.github-token") + .accessibility(.whenUnlocked) + +keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +###### One-shot + +```swift +let keychain = Keychain(service: "com.example.github-token") + +do { + try keychain + .accessibility(.whenUnlocked) + .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") +} catch let error { + print("error: \(error)") +} +``` + +#### :couple: Sharing Keychain items + +```swift +let keychain = Keychain(service: "com.example.github-token", accessGroup: "12ABCD3E4F.shared") +``` + +#### :arrows_counterclockwise: Synchronizing Keychain items with iCloud + +###### Creating instance + +```swift +let keychain = Keychain(service: "com.example.github-token") + .synchronizable(true) + +keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef" +``` + +###### One-shot + +```swift +let keychain = Keychain(service: "com.example.github-token") + +do { + try keychain + .synchronizable(true) + .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") +} catch let error { + print("error: \(error)") +} +``` + +### :fu: Touch ID integration + +**Any Operation that require authentication must be run in the background thread.** +**If you run in the main thread, UI thread will lock for the system to try to display the authentication dialog.** + +#### :closed_lock_with_key: Adding a Touch ID protected item + +If you want to store the Touch ID protected Keychain item, specify `accessibility` and `authenticationPolicy` attributes. + +```swift +let keychain = Keychain(service: "com.example.github-token") + +DispatchQueue.global().async { + do { + // Should be the secret invalidated when passcode is removed? If not then use `.WhenUnlocked` + try keychain + .accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence) + .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") + } catch let error { + // Error handling if needed... + } +} +``` + +#### :closed_lock_with_key: Updating a Touch ID protected item + +The same way as when adding. + +**Do not run in the main thread if there is a possibility that the item you are trying to add already exists, and protected.** +**Because updating protected items requires authentication.** + +Additionally, you want to show custom authentication prompt message when updating, specify an `authenticationPrompt` attribute. +If the item not protected, the `authenticationPrompt` parameter just be ignored. + +```swift +let keychain = Keychain(service: "com.example.github-token") + +DispatchQueue.global().async { + do { + // Should be the secret invalidated when passcode is removed? If not then use `.WhenUnlocked` + try keychain + .accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence) + .authenticationPrompt("Authenticate to update your access token") + .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") + } catch let error { + // Error handling if needed... + } +} +``` + +#### :closed_lock_with_key: Obtaining a Touch ID protected item + +The same way as when you get a normal item. It will be displayed automatically Touch ID or passcode authentication If the item you try to get is protected. +If you want to show custom authentication prompt message, specify an `authenticationPrompt` attribute. +If the item not protected, the `authenticationPrompt` parameter just be ignored. + +```swift +let keychain = Keychain(service: "com.example.github-token") + +DispatchQueue.global().async { + do { + let password = try keychain + .authenticationPrompt("Authenticate to login to server") + .get("kishikawakatsumi") + + print("password: \(password)") + } catch let error { + // Error handling if needed... + } +} +``` + +#### :closed_lock_with_key: Removing a Touch ID protected item + +The same way as when you remove a normal item. +There is no way to show Touch ID or passcode authentication when removing Keychain items. + +```swift +let keychain = Keychain(service: "com.example.github-token") + +do { + try keychain.remove("kishikawakatsumi") +} catch let error { + // Error handling if needed... +} +``` + +### :key: Shared Web Credentials + +> Shared web credentials is a programming interface that enables native iOS apps to share credentials with their website counterparts. For example, a user may log in to a website in Safari, entering a user name and password, and save those credentials using the iCloud Keychain. Later, the user may run a native app from the same developer, and instead of the app requiring the user to reenter a user name and password, shared web credentials gives it access to the credentials that were entered earlier in Safari. The user can also create new accounts, update passwords, or delete her account from within the app. These changes are then saved and used by Safari. + + + +```swift +let keychain = Keychain(server: "https://www.kishikawakatsumi.com", protocolType: .HTTPS) + +let username = "kishikawakatsumi@mac.com" + +// First, check the credential in the app's Keychain +if let password = try? keychain.get(username) { + // If found password in the Keychain, + // then log into the server +} else { + // If not found password in the Keychain, + // try to read from Shared Web Credentials + keychain.getSharedPassword(username) { (password, error) -> () in + if password != nil { + // If found password in the Shared Web Credentials, + // then log into the server + // and save the password to the Keychain + + keychain[username] = password + } else { + // If not found password either in the Keychain also Shared Web Credentials, + // prompt for username and password + + // Log into server + + // If the login is successful, + // save the credentials to both the Keychain and the Shared Web Credentials. + + keychain[username] = inputPassword + keychain.setSharedPassword(inputPassword, account: username) + } + } +} +``` + +#### Request all associated domain's credentials + +```swift +Keychain.requestSharedWebCredential { (credentials, error) -> () in + +} +``` + +#### Generate strong random password + +Generate strong random password that is in the same format used by Safari autofill (xxx-xxx-xxx-xxx). + +```swift +let password = Keychain.generatePassword() // => Nhu-GKm-s3n-pMx +``` + +#### How to set up Shared Web Credentials + +> 1. Add a com.apple.developer.associated-domains entitlement to your app. This entitlement must include all the domains with which you want to share credentials. + +> 2. Add an apple-app-site-association file to your website. This file must include application identifiers for all the apps with which the site wants to share credentials, and it must be properly signed. + +> 3. When the app is installed, the system downloads and verifies the site association file for each of its associated domains. If the verification is successful, the app is associated with the domain. + +**More details:** + + +### :key: Debugging + +#### Display all stored items if print keychain object + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https) +print("\(keychain)") +``` + +``` +=> +[ + [authenticationType: default, key: kishikawakatsumi, server: github.com, class: internetPassword, protocol: https] + [authenticationType: default, key: hirohamada, server: github.com, class: internetPassword, protocol: https] + [authenticationType: default, key: honeylemon, server: github.com, class: internetPassword, protocol: https] +] +``` + +#### Obtaining all stored keys + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https) + +let keys = keychain.allKeys() +for key in keys { + print("key: \(key)") +} +``` + +``` +=> +key: kishikawakatsumi +key: hirohamada +key: honeylemon +``` + +#### Obtaining all stored items + +```swift +let keychain = Keychain(server: "https://github.com", protocolType: .https) + +let items = keychain.allItems() +for item in items { + print("item: \(item)") +} +``` + +``` +=> +item: [authenticationType: Default, key: kishikawakatsumi, server: github.com, class: InternetPassword, protocol: https] +item: [authenticationType: Default, key: hirohamada, server: github.com, class: InternetPassword, protocol: https] +item: [authenticationType: Default, key: honeylemon, server: github.com, class: InternetPassword, protocol: https] +``` + +## Requirements + +| | OS | Swift | +|------------|----------------------------------------|---------------| +| **v1.1.x** | iOS 7+, OSX 10.9+ | 1.1 | +| **v1.2.x** | iOS 7+, OSX 10.9+ | 1.2 | +| **v2.0.x** | iOS 7+, OSX 10.9+, watchOS 2+ | 2.0 | +| **v2.1.x** | iOS 7+, OSX 10.9+, watchOS 2+ | 2.0 | +| **v2.2.x** | iOS 8+, OSX 10.9+, watchOS 2+, tvOS 9+ | 2.0, 2.1 | +| **v2.3.x** | iOS 8+, OSX 10.9+, watchOS 2+, tvOS 9+ | 2.0, 2.1, 2.2 | +| **v2.4.x** | iOS 8+, OSX 10.9+, watchOS 2+, tvOS 9+ | 2.2, 2.3 | +| **v3.0.x** | iOS 8+, OSX 10.9+, watchOS 2+, tvOS 9+ | 3.x | +| **v3.1.x** | iOS 8+, OSX 10.9+, watchOS 2+, tvOS 9+ | 4.0, 4.1, 4.2 | + +## Installation + +### CocoaPods + +KeychainAccess is available through [CocoaPods](http://cocoapods.org). To install +it, simply add the following lines to your Podfile: + +```ruby +use_frameworks! +pod 'KeychainAccess' +``` + +### Carthage + +KeychainAccess is available through [Carthage](https://github.com/Carthage/Carthage). To install +it, simply add the following line to your Cartfile: + +`github "kishikawakatsumi/KeychainAccess"` + +### Swift Package Manager + +KeychainAccess is also available through [Swift Package Manager](https://github.com/apple/swift-package-manager/). +First, create `Package.swift` that its package declaration includes: + +```swift +import PackageDescription + +let package = Package( + dependencies: [ + .Package(url: "https://github.com/kishikawakatsumi/KeychainAccess.git", majorVersion: 2) + ] +) +``` + +Then, type + +```shell +$ swift build +``` + +### To manually add to your project + +1. Add `Lib/KeychainAccess.xcodeproj` to your project +2. Link `KeychainAccess.framework` with your target +3. Add `Copy Files Build Phase` to include the framework to your application bundle + +_See [iOS Example Project](https://github.com/kishikawakatsumi/KeychainAccess/tree/master/Examples/Example-iOS) as reference._ + + + +## Author + +kishikawa katsumi, kishikawakatsumi@mac.com + +## License + +KeychainAccess is available under the MIT license. See the LICENSE file for more info. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/Anchorage.podspec.json b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/Anchorage.podspec.json new file mode 100644 index 0000000..4973d97 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/Anchorage.podspec.json @@ -0,0 +1,22 @@ +{ + "name": "Anchorage", + "version": "4.3", + "summary": "A collection of operators and utilities that simplify iOS layout code.", + "description": "Create constraints using intuitive operators built directly on top of the NSLayoutAnchor API. Layout has never been simpler!", + "homepage": "https://github.com/Raizlabs/Anchorage", + "license": "MIT", + "authors": { + "Rob Visentin": "rob.visentin@raizlabs.com" + }, + "source": { + "git": "https://github.com/Raizlabs/Anchorage.git", + "tag": "4.3" + }, + "platforms": { + "ios": "9.0", + "tvos": "9.0", + "osx": "10.11" + }, + "requires_arc": true, + "source_files": "Source/**/*.swift" +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/BonMot.podspec.json b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/BonMot.podspec.json new file mode 100644 index 0000000..0aac4d8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/BonMot.podspec.json @@ -0,0 +1,36 @@ +{ + "name": "BonMot", + "version": "5.2", + "summary": "Beautiful, easy attributed strings in Swift", + "swift_version": "4.2", + "description": "BonMot removes all the mystery from creating beautiful, powerful attributed strings in Swift.", + "homepage": "https://github.com/Raizlabs/BonMot", + "license": "MIT", + "authors": { + "Zev Eisenberg": "zev.eisenberg@raizlabs.com" + }, + "source": { + "git": "https://github.com/Raizlabs/BonMot.git", + "tag": "5.2" + }, + "social_media_url": "https://twitter.com/ZevEisenberg", + "requires_arc": true, + "platforms": { + "ios": "9.0", + "tvos": "9.0", + "osx": "10.11", + "watchos": "2.2" + }, + "ios": { + "source_files": "Sources/**/*.swift" + }, + "tvos": { + "source_files": "Sources/**/*.swift" + }, + "osx": { + "source_files": "Sources/*.swift" + }, + "watchos": { + "source_files": "Sources/*.swift" + } +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/Swiftilities.podspec.json b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/Swiftilities.podspec.json new file mode 100644 index 0000000..49e7fb3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Local Podspecs/Swiftilities.podspec.json @@ -0,0 +1,314 @@ +{ + "name": "Swiftilities", + "version": "0.19.0", + "summary": "A collection of useful Swift utilities.", + "swift_version": "4.2", + "description": "A collection of useful Swift utilities. All components and\nextensions found in this library are consise enough on their own\nso as to not warrant their own project.", + "homepage": "https://github.com/raizlabs/Swiftilities", + "license": "MIT", + "authors": { + "Nicholas Bonatsakis": "nick.bonatsakis@raizlabs.com" + }, + "source": { + "git": "https://github.com/raizlabs/Swiftilities.git", + "tag": "0.19.0" + }, + "platforms": { + "ios": "9.0" + }, + "requires_arc": true, + "default_subspecs": "All", + "subspecs": [ + { + "name": "AboutView", + "source_files": "Pod/Classes/AboutView/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "AccessibilityHelpers", + "source_files": "Pod/Classes/AccessibilityHelpers/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "Acknowledgements", + "dependencies": { + "Swiftilities/LicenseFormatter": [ + + ], + "Swiftilities/Deselection": [ + + ], + "Swiftilities/Compatibility": [ + + ] + }, + "source_files": "Pod/Classes/Acknowledgements/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "BetterButton", + "source_files": "Pod/Classes/BetterButton/*.swift", + "dependencies": { + "Swiftilities/Shapes": [ + + ], + "Swiftilities/ImageHelpers": [ + + ], + "Swiftilities/ColorHelpers": [ + + ], + "Swiftilities/Math": [ + + ] + }, + "frameworks": [ + "UIKit" + ] + }, + { + "name": "ColorHelpers", + "source_files": "Pod/Classes/ColorHelpers/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "Compatibility", + "source_files": "Pod/Classes/Compatibility/*.swift" + }, + { + "name": "CoreDataStack", + "source_files": "Pod/Classes/CoreDataStack/*.swift", + "frameworks": [ + "Foundation", + "CoreData" + ] + }, + { + "name": "Deselection", + "source_files": "Pod/Classes/Deselection/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "DeviceSize", + "source_files": "Pod/Classes/DeviceSize/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "FormattedTextField", + "source_files": "Pod/Classes/FormattedTextField/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "Forms", + "source_files": "Pod/Classes/Forms/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "HairlineView", + "source_files": "Pod/Classes/HairlineView/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "ImageHelpers", + "source_files": "Pod/Classes/ImageHelpers/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "Keyboard", + "source_files": "Pod/Classes/Keyboard/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "LicenseFormatter", + "source_files": "Pod/Classes/LicenseFormatter/*.swift", + "frameworks": "Foundation" + }, + { + "name": "Lifecycle", + "dependencies": { + "Swiftilities/Math": [ + + ], + "Swiftilities/HairlineView": [ + + ] + }, + "source_files": [ + "Pod/Classes/Lifecycle/**/*.swift" + ], + "frameworks": [ + "UIKit" + ] + }, + { + "name": "Logging", + "source_files": "Pod/Classes/Logging/*.swift", + "frameworks": "Foundation" + }, + { + "name": "Math", + "platforms": { + "ios": "9.0", + "tvos": "9.0", + "osx": "10.11", + "watchos": "2.2" + }, + "ios": { + "source_files": "Pod/Classes/Math/*.swift" + }, + "tvos": { + "source_files": "Pod/Classes/Math/*.swift" + }, + "osx": { + "source_files": "Pod/Classes/Math/*.swift" + }, + "watchos": { + "source_files": "Pod/Classes/Math/*.swift" + } + }, + { + "name": "RootViewController", + "source_files": "Pod/Classes/RootViewController/*.swift", + "frameworks": [ + "UIKit", + "MessageUI" + ] + }, + { + "name": "Shapes", + "source_files": "Pod/Classes/Shapes/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "StackViewHelpers", + "source_files": "Pod/Classes/StackViewHelpers/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "TableViewHelpers", + "source_files": "Pod/Classes/TableViewHelpers/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "TintedButton", + "source_files": "Pod/Classes/TintedButton/*.swift", + "frameworks": [ + "UIKit" + ] + }, + { + "name": "Views", + "source_files": [ + "Pod/Classes/Views/**/*.swift" + ], + "frameworks": [ + "UIKit" + ] + }, + { + "name": "All", + "dependencies": { + "Swiftilities/AboutView": [ + + ], + "Swiftilities/AccessibilityHelpers": [ + + ], + "Swiftilities/Acknowledgements": [ + + ], + "Swiftilities/BetterButton": [ + + ], + "Swiftilities/ColorHelpers": [ + + ], + "Swiftilities/Compatibility": [ + + ], + "Swiftilities/CoreDataStack": [ + + ], + "Swiftilities/Deselection": [ + + ], + "Swiftilities/DeviceSize": [ + + ], + "Swiftilities/FormattedTextField": [ + + ], + "Swiftilities/Forms": [ + + ], + "Swiftilities/HairlineView": [ + + ], + "Swiftilities/ImageHelpers": [ + + ], + "Swiftilities/Keyboard": [ + + ], + "Swiftilities/LicenseFormatter": [ + + ], + "Swiftilities/Lifecycle": [ + + ], + "Swiftilities/Logging": [ + + ], + "Swiftilities/Math": [ + + ], + "Swiftilities/RootViewController": [ + + ], + "Swiftilities/Shapes": [ + + ], + "Swiftilities/StackViewHelpers": [ + + ], + "Swiftilities/TableViewHelpers": [ + + ], + "Swiftilities/TintedButton": [ + + ], + "Swiftilities/Views": [ + + ] + } + } + ] +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Manifest.lock b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Manifest.lock new file mode 100644 index 0000000..491ed15 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Manifest.lock @@ -0,0 +1,227 @@ +PODS: + - Alamofire (4.8.2) + - Anchorage (4.3) + - AppCenter/Core (2.0.1) + - AppCenter/Distribute (2.0.1): + - AppCenter/Core + - BonMot (5.3) + - Crashlytics (3.12.0): + - Fabric (~> 1.9.0) + - Fabric (1.9.0) + - Firebase/Core (6.0.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.0.0) + - Firebase/CoreOnly (6.0.0): + - FirebaseCore (= 6.0.0) + - Firebase/Messaging (6.0.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 4.0.0) + - FirebaseAnalytics (6.0.0): + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleAppMeasurement (= 6.0.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - FirebaseAnalyticsInterop (1.2.0) + - FirebaseCore (6.0.0): + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Logger (~> 6.0) + - FirebaseInstanceID (4.0.0): + - FirebaseCore (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - FirebaseMessaging (4.0.0): + - FirebaseAnalyticsInterop (~> 1.1) + - FirebaseCore (~> 6.0) + - FirebaseInstanceID (~> 4.0) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/Reachability (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - Protobuf (~> 3.1) + - GoogleAppMeasurement (6.0.0): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 0.3) + - GoogleUtilities/AppDelegateSwizzler (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.0.0) + - GoogleUtilities/Logger (6.0.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.0.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.0.0)" + - GoogleUtilities/Reachability (6.0.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.0.0): + - GoogleUtilities/Logger + - Instabug (8.3) + - KeychainAccess (3.2.0) + - nanopb (0.3.901): + - nanopb/decode (= 0.3.901) + - nanopb/encode (= 0.3.901) + - nanopb/decode (0.3.901) + - nanopb/encode (0.3.901) + - OHHTTPStubs/Core (8.0.0) + - OHHTTPStubs/Default (8.0.0): + - OHHTTPStubs/Core + - OHHTTPStubs/JSON + - OHHTTPStubs/NSURLSession + - OHHTTPStubs/OHPathHelpers + - OHHTTPStubs/JSON (8.0.0): + - OHHTTPStubs/Core + - OHHTTPStubs/NSURLSession (8.0.0): + - OHHTTPStubs/Core + - OHHTTPStubs/OHPathHelpers (8.0.0) + - OHHTTPStubs/Swift (8.0.0): + - OHHTTPStubs/Default + - Protobuf (3.7.0) + - SimulatorStatusMagic (2.4.1) + - Sourcery (0.16.1) + - SwiftGen (6.1.0) + - Swiftilities (0.22.1): + - Swiftilities/All (= 0.22.1) + - Swiftilities/AboutView (0.22.1) + - Swiftilities/AccessibilityHelpers (0.22.1) + - Swiftilities/Acknowledgements (0.22.1): + - Swiftilities/Compatibility + - Swiftilities/Deselection + - Swiftilities/LicenseFormatter + - Swiftilities/All (0.22.1): + - Swiftilities/AboutView + - Swiftilities/AccessibilityHelpers + - Swiftilities/Acknowledgements + - Swiftilities/BetterButton + - Swiftilities/ColorHelpers + - Swiftilities/Compatibility + - Swiftilities/CoreDataStack + - Swiftilities/Deselection + - Swiftilities/DeviceSize + - Swiftilities/FormattedTextField + - Swiftilities/Forms + - Swiftilities/HairlineView + - Swiftilities/ImageHelpers + - Swiftilities/Keyboard + - Swiftilities/LicenseFormatter + - Swiftilities/Lifecycle + - Swiftilities/Logging + - Swiftilities/Math + - Swiftilities/RootViewController + - Swiftilities/Shapes + - Swiftilities/StackViewHelpers + - Swiftilities/TableViewHelpers + - Swiftilities/TintedButton + - Swiftilities/Views + - Swiftilities/BetterButton (0.22.1): + - Swiftilities/ColorHelpers + - Swiftilities/ImageHelpers + - Swiftilities/Math + - Swiftilities/Shapes + - Swiftilities/ColorHelpers (0.22.1) + - Swiftilities/Compatibility (0.22.1) + - Swiftilities/CoreDataStack (0.22.1) + - Swiftilities/Deselection (0.22.1) + - Swiftilities/DeviceSize (0.22.1) + - Swiftilities/FormattedTextField (0.22.1) + - Swiftilities/Forms (0.22.1) + - Swiftilities/HairlineView (0.22.1) + - Swiftilities/ImageHelpers (0.22.1) + - Swiftilities/Keyboard (0.22.1) + - Swiftilities/LicenseFormatter (0.22.1) + - Swiftilities/Lifecycle (0.22.1): + - Swiftilities/HairlineView + - Swiftilities/Math + - Swiftilities/Logging (0.22.1) + - Swiftilities/Math (0.22.1) + - Swiftilities/RootViewController (0.22.1) + - Swiftilities/Shapes (0.22.1) + - Swiftilities/StackViewHelpers (0.22.1) + - Swiftilities/TableViewHelpers (0.22.1) + - Swiftilities/TintedButton (0.22.1) + - Swiftilities/Views (0.22.1) + - SwiftLint (0.32.0) + +DEPENDENCIES: + - Alamofire + - Anchorage + - AppCenter/Distribute + - BonMot + - Crashlytics + - Firebase/Core + - Firebase/Messaging + - Instabug + - KeychainAccess + - OHHTTPStubs/Swift + - SimulatorStatusMagic + - Sourcery (~> 0.16.1) + - SwiftGen + - Swiftilities + - SwiftLint + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - Alamofire + - Anchorage + - AppCenter + - BonMot + - Crashlytics + - Fabric + - Firebase + - FirebaseAnalytics + - FirebaseAnalyticsInterop + - FirebaseCore + - FirebaseInstanceID + - FirebaseMessaging + - GoogleAppMeasurement + - GoogleUtilities + - Instabug + - KeychainAccess + - nanopb + - OHHTTPStubs + - Protobuf + - SimulatorStatusMagic + - Sourcery + - SwiftGen + - Swiftilities + - SwiftLint + +SPEC CHECKSUMS: + Alamofire: ae5c501addb7afdbb13687d7f2f722c78734c2d3 + Anchorage: 21a98675245188427f0bcea21404d42a824a766f + AppCenter: 6a5ff2fd007b53431259fdd74f91eb3d0dfea3d1 + BonMot: 0104d1b4eda54f4a4b7393d6559539ef25498fbd + Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 + Fabric: f988e33c97f08930a413e08123064d2e5f68d655 + Firebase: fa80b9d987ca014a1ba9357496ef2a0178b28b12 + FirebaseAnalytics: 1743c5f4de3687d0745709dfdc4b1dea1484f44c + FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1 + FirebaseCore: e38f025287b413255a53acc1945d048a112047f7 + FirebaseInstanceID: 0e0348a3c00a734fa376a070f5ad4533ad975cb5 + FirebaseMessaging: c796d50864dc822a3c06c9c1c1444b37732b795b + GoogleAppMeasurement: 7f028ea162b72c8f326daec74afc95d94f7a47d6 + GoogleUtilities: f1faafc033ea203adf1783ce00af455bb99d0e5b + Instabug: c61ac1b653b64596c1bd00cf5ba039f05aecb930 + KeychainAccess: 3b1bf8a77eb4c6ea1ce9404c292e48f948954c6b + nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48 + OHHTTPStubs: 9cbce6364bec557cc3439aa6bb7514670d780881 + Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a + SimulatorStatusMagic: 28d4a9d1a500ac7cea0b2b5a43c1c6ddb40ba56c + Sourcery: 16779170d35ee204666843b09031f36721a84bcc + SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0 + Swiftilities: 7b57b06b46df20236a1cd9faf64ab3fd7554f4ed + SwiftLint: 009a898ef2a1c851f45e1b59349bf6ff2ddc990d + +PODFILE CHECKSUM: f4deff92cb777959f68cae8d4fd0677ec3f2443f + +COCOAPODS: 1.7.5 diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/LICENSE new file mode 100644 index 0000000..a83928d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/LICENSE @@ -0,0 +1,9 @@ +- MIT LICENSE - + +Copyright (c) 2012 Olivier Halligon + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/Compatibility.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/Compatibility.h new file mode 100644 index 0000000..b41ddda --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/Compatibility.h @@ -0,0 +1,47 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +/* + * This file allows to keep compatibility with older SDKs which didn't have + * the latest features and associated macros yet. + */ + + +#ifndef NS_DESIGNATED_INITIALIZER + #if __has_attribute(objc_designated_initializer) + #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) + #else + #define NS_DESIGNATED_INITIALIZER + #endif +#endif + +// Allow to use nullability macros and keywords even if not supported yet +#if ! __has_feature(nullability) + #define NS_ASSUME_NONNULL_BEGIN + #define NS_ASSUME_NONNULL_END + #define nullable + #define __nullable + #define __nonnull +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h new file mode 100644 index 0000000..cdcacb5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h @@ -0,0 +1,57 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +#import "OHHTTPStubsResponse.h" +#import "Compatibility.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Adds convenience methods to manipulate JSON objects directly. + * Pass in an `NSDictionary` or `NSArray` to generate a corresponding JSON output. + */ +@interface OHHTTPStubsResponse (JSON) + +/** + * Builds a response given a JSON object for the response body, status code, and headers. + * + * @param jsonObject Object representing the response body. + * Typically a `NSDictionary`; may be any object accepted by `+[NSJSONSerialization dataWithJSONObject:options:error:]` + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * If a "Content-Type" header is not included, "Content-Type: application/json" will be added. + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note This method typically calls `responseWithData:statusCode:headers:`, passing the serialized JSON + * object as the data parameter and adding the Content-Type header if necessary. + */ ++ (instancetype)responseWithJSONObject:(id)jsonObject + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.m new file mode 100644 index 0000000..75405df --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.m @@ -0,0 +1,48 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +#import "OHHTTPStubsResponse+JSON.h" + +@implementation OHHTTPStubsResponse (JSON) + +/*! @name Building a response from JSON objects */ + ++ (instancetype)responseWithJSONObject:(id)jsonObject + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders +{ + if (!httpHeaders[@"Content-Type"]) + { + NSMutableDictionary* mutableHeaders = [NSMutableDictionary dictionaryWithDictionary:httpHeaders]; + mutableHeaders[@"Content-Type"] = @"application/json"; + httpHeaders = [NSDictionary dictionaryWithDictionary:mutableHeaders]; // make immutable again + } + + return [self responseWithData:[NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:nil] + statusCode:statusCode + headers:httpHeaders]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.h new file mode 100644 index 0000000..44979c4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.h @@ -0,0 +1,48 @@ +/*********************************************************************************** +* +* Copyright (c) 2016 Sebastian Hagedorn, Felix Lamouroux +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +***********************************************************************************/ + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import + +// This category is only useful when NSURLSession is present +#if defined(__IPHONE_7_0) || defined(__MAC_10_9) + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - NSURLRequest+HTTPBodyTesting + +@interface NSURLRequest (HTTPBodyTesting) +/** + * Unfortunately, when sending POST requests (with a body) using NSURLSession, + * by the time the request arrives at OHHTTPStubs, the HTTPBody of the + * NSURLRequest has been reset to nil. + * + * You can use this method to retrieve the HTTPBody for testing and use it to + * conditionally stub your requests. + */ +- (NSData *)OHHTTPStubs_HTTPBody; +@end + +#endif /* __IPHONE_7_0 || __MAC_10_9 */ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.m new file mode 100644 index 0000000..a2ff7e8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.m @@ -0,0 +1,86 @@ +/*********************************************************************************** +* +* Copyright (c) 2016 Sebastian Hagedorn, Felix Lamouroux +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +***********************************************************************************/ + +#import "NSURLRequest+HTTPBodyTesting.h" + +#if defined(__IPHONE_7_0) || defined(__MAC_10_9) + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import "OHHTTPStubsMethodSwizzling.h" + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - NSURLRequest+CustomHTTPBody + +NSString * const OHHTTPStubs_HTTPBodyKey = @"HTTPBody"; + +@implementation NSURLRequest (HTTPBodyTesting) + +- (NSData*)OHHTTPStubs_HTTPBody +{ + return [NSURLProtocol propertyForKey:OHHTTPStubs_HTTPBodyKey inRequest:self]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - NSMutableURLRequest+HTTPBodyTesting + +typedef void(*OHHHTTPStubsSetterIMP)(id, SEL, id); +static OHHHTTPStubsSetterIMP orig_setHTTPBody; + +static void OHHTTPStubs_setHTTPBody(id self, SEL _cmd, NSData* HTTPBody) +{ + // store the http body via NSURLProtocol + if (HTTPBody) { + [NSURLProtocol setProperty:HTTPBody forKey:OHHTTPStubs_HTTPBodyKey inRequest:self]; + } else { + // unfortunately resetting does not work properly as the NSURLSession also uses this to reset the property + } + + orig_setHTTPBody(self, _cmd, HTTPBody); +} + +/** + * Swizzles setHTTPBody: in order to maintain a copy of the http body for later + * reference and calls the original implementation. + * + * @warning Should not be used in production, testing only. + */ +@interface NSMutableURLRequest (HTTPBodyTesting) @end + +@implementation NSMutableURLRequest (HTTPBodyTesting) + ++ (void)load +{ + orig_setHTTPBody = (OHHHTTPStubsSetterIMP)OHHTTPStubsReplaceMethod(@selector(setHTTPBody:), + (IMP)OHHTTPStubs_setHTTPBody, + [NSMutableURLRequest class], + NO); +} + +@end + +#endif /* __IPHONE_7_0 || __MAC_10_9 */ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m new file mode 100644 index 0000000..6e88515 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m @@ -0,0 +1,78 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + +#import + +#if defined(__IPHONE_7_0) || defined(__MAC_10_9) +#import "OHHTTPStubs.h" +#import "OHHTTPStubsMethodSwizzling.h" + +////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This helper is used to swizzle NSURLSessionConfiguration constructor methods + * defaultSessionConfiguration and ephemeralSessionConfiguration to insert the private + * OHHTTPStubsProtocol into their protocolClasses array so that OHHTTPStubs is automagically + * supported when you create a new NSURLSession based on one of there configurations. + */ + +typedef NSURLSessionConfiguration*(*SessionConfigConstructor)(id,SEL); +static SessionConfigConstructor orig_defaultSessionConfiguration; +static SessionConfigConstructor orig_ephemeralSessionConfiguration; + +static NSURLSessionConfiguration* OHHTTPStubs_defaultSessionConfiguration(id self, SEL _cmd) +{ + NSURLSessionConfiguration* config = orig_defaultSessionConfiguration(self,_cmd); // call original method + [OHHTTPStubs setEnabled:YES forSessionConfiguration:config]; //OHHTTPStubsAddProtocolClassToNSURLSessionConfiguration(config); + return config; +} + +static NSURLSessionConfiguration* OHHTTPStubs_ephemeralSessionConfiguration(id self, SEL _cmd) +{ + NSURLSessionConfiguration* config = orig_ephemeralSessionConfiguration(self,_cmd); // call original method + [OHHTTPStubs setEnabled:YES forSessionConfiguration:config]; //OHHTTPStubsAddProtocolClassToNSURLSessionConfiguration(config); + return config; +} + +@interface NSURLSessionConfiguration(OHHTTPStubsSupport) @end + +@implementation NSURLSessionConfiguration(OHHTTPStubsSupport) + ++(void)load +{ + orig_defaultSessionConfiguration = (SessionConfigConstructor)OHHTTPStubsReplaceMethod(@selector(defaultSessionConfiguration), + (IMP)OHHTTPStubs_defaultSessionConfiguration, + [NSURLSessionConfiguration class], + YES); + orig_ephemeralSessionConfiguration = (SessionConfigConstructor)OHHTTPStubsReplaceMethod(@selector(ephemeralSessionConfiguration), + (IMP)OHHTTPStubs_ephemeralSessionConfiguration, + [NSURLSessionConfiguration class], + YES); +} + +@end + +#endif /* __IPHONE_7_0 || __MAC_10_9 */ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.h new file mode 100644 index 0000000..443a680 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.h @@ -0,0 +1,51 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon, 2016 Sebastian Hagedorn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Method Swizzling Helpers + +/** + * Replaces the selector's associated method implementation with the + * given implementation (or adds it, if there was no existing one). + * + * @param selector The selector entry in the dispatch table. + * @param newImpl The implementation that will be associated with + * the given selector. + * @param affectedClass The class whose dispatch table will be altered. + * @param isClassMethod Set to YES if the selector denotes a class + * method, or NO if it is an instance method. + * @return The previous implementation associated with + * the swizzled selector. You should store the + * implementation and call it when overwriting + * the selector. + */ +__attribute__((warn_unused_result)) IMP OHHTTPStubsReplaceMethod(SEL selector, + IMP newImpl, + Class affectedClass, + BOOL isClassMethod); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.m new file mode 100644 index 0000000..2aefcc7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.m @@ -0,0 +1,47 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon, 2016 Sebastian Hagedorn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import "OHHTTPStubsMethodSwizzling.h" + +////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Method Swizzling Helpers + +IMP OHHTTPStubsReplaceMethod(SEL selector, + IMP newImpl, + Class affectedClass, + BOOL isClassMethod) +{ + Method origMethod = isClassMethod ? class_getClassMethod(affectedClass, selector) : class_getInstanceMethod(affectedClass, selector); + IMP origImpl = method_getImplementation(origMethod); + + if (!class_addMethod(isClassMethod ? object_getClass(affectedClass) : affectedClass, selector, newImpl, method_getTypeEncoding(origMethod))) + { + method_setImplementation(origMethod, newImpl); + } + + return origImpl; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h new file mode 100644 index 0000000..964ac7a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h @@ -0,0 +1,219 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import + +#import "Compatibility.h" +#import "OHHTTPStubsResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Types + +typedef BOOL(^OHHTTPStubsTestBlock)(NSURLRequest* request); +typedef OHHTTPStubsResponse* __nonnull (^OHHTTPStubsResponseBlock)( NSURLRequest* request); + +/** + * This opaque type represents an installed stub and is used to uniquely + * identify a stub once it has been created. + * + * This type is returned by the `stubRequestsPassingTest:withStubResponse:` method + * so that you can later reference it and use this reference to remove the stub later. + * + * This type also let you add arbitrary metadata to a stub to differenciate it + * more easily when debugging. + */ +@protocol OHHTTPStubsDescriptor +/** + * An arbitrary name that you can set and get to describe your stub. + * Use it as your own convenience. + * + * This is especially useful if you dump all installed stubs using `allStubs` + * or if you want to log which stubs are being triggered using `onStubActivation:`. + */ +@property(nonatomic, strong, nullable) NSString* name; +@end + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Interface + +/** + * Stubs Manager. Use this class to add and remove stubs and stub your network requests. + */ +@interface OHHTTPStubs : NSObject + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Adding & Removing stubs + + + +/** + * Dedicated method to add a stub + * + * @param testBlock Block that should return `YES` if the request passed as parameter + * should be stubbed with the response block, and `NO` if it should + * hit the real world (or be managed by another stub). + * @param responseBlock Block that will return the `OHHTTPStubsResponse` (response to + * use for stubbing) corresponding to the given request + * + * @return a stub descriptor that uniquely identifies the stub and can be later used to remove it with `removeStub:`. + * + * @note The returned stub descriptor is retained (`__strong` reference) by `OHHTTPStubs` + * until it is removed (with one of the `removeStub:` / `removeAllStubs` + * methods); it is thus recommended to keep it in a `__weak` storage (and not `__strong`) + * in your app code, to let the stub descriptor be destroyed and let the variable go + * back to `nil` automatically when the stub is removed. + */ ++(id)stubRequestsPassingTest:(OHHTTPStubsTestBlock)testBlock + withStubResponse:(OHHTTPStubsResponseBlock)responseBlock; + +/** + * Remove a stub from the list of stubs + * + * @param stubDesc The stub descriptor that has been returned when adding the stub + * using `stubRequestsPassingTest:withStubResponse:` + * + * @return `YES` if the stub has been successfully removed, `NO` if the parameter was + * not a valid stub identifier + */ ++(BOOL)removeStub:(id)stubDesc; + +/** + * Remove all the stubs from the stubs list. + */ ++(void)removeAllStubs; + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Disabling & Re-Enabling stubs + +/** + * Enable or disable the stubs for the shared session or for `NSURLConnection` + * + * @param enabled If `YES`, enables the stubs. If `NO`, disable all the + * stubs and let all the requests hit the real world. + * + * @note OHHTTPStubs are enabled by default, so there is no need to call + * this method with `YES` for stubs to work, except if you explicitely + * disabled the stubs before. + * + * @note This only affects requests that are further made using `NSURLConnection` + * or using `[NSURLSession sharedSession]`. This does not affect requests + * sent on an `NSURLSession` created using an `NSURLSessionConfiguration`. + */ ++(void)setEnabled:(BOOL)enabled; + +/** + * Whether or not stubs are enabled for the shared session or for `NSURLConnection` + * + * @return If `YES` the stubs are enabled. If `NO` then the stubs are disabled + */ ++(BOOL)isEnabled; + +#if defined(__IPHONE_7_0) || defined(__MAC_10_9) +/** + * Enable or disable the stubs on a given `NSURLSessionConfiguration`. + * + * @param enabled If `YES`, enables the stubs for this `NSURLSessionConfiguration`. + * If `NO`, disable the stubs and let all the requests hit the real world + * @param sessionConfig The NSURLSessionConfiguration on which to enabled/disable the stubs + * + * @note OHHTTPStubs are enabled by default on newly created `defaultSessionConfiguration` + * and `ephemeralSessionConfiguration`, so there is no need to call this method with + * `YES` for stubs to work. You generally only use this if you want to disable + * `OHTTPStubs` per `NSURLSession` by calling it before building the `NSURLSession` + * with the `NSURLSessionConfiguration`. + * + * @note Important: As usual according to the way `NSURLSessionConfiguration` works, you + * MUST set this property BEFORE creating the `NSURLSession`. Once the `NSURLSession` + * object is created, they use a deep copy of the `NSURLSessionConfiguration` object + * used to create them, so changing the configuration later does not affect already + * created sessions. + */ ++ (void)setEnabled:(BOOL)enabled forSessionConfiguration:(NSURLSessionConfiguration *)sessionConfig; + +/** + * Whether stubs are enabled or disabled on a given `NSURLSessionConfiguration` + * + * @param sessionConfig The NSURLSessionConfiguration on which to enable/disable the stubs + * + * @return If `YES` the stubs are enabled for sessionConfig. If `NO` then the stubs are disabled + */ ++ (BOOL)isEnabledForSessionConfiguration:(NSURLSessionConfiguration *)sessionConfig; +#endif + +#pragma mark - Debug Methods + +/** + * List all the installed stubs + * + * @return An array of `id` objects currently installed. Useful for debug. + */ ++(NSArray*)allStubs; + +/** + * Setup a block to be called each time a stub is triggered. + * + * Useful if you want to log all your requests being stubbed for example and see which stub + * was used to respond to each request. + * + * @param block The block to call each time a request is being stubbed by OHHTTPStubs. + * Set it to `nil` to do nothing. Defaults is `nil`. + */ ++(void)onStubActivation:( nullable void(^)(NSURLRequest* request, id stub, OHHTTPStubsResponse* responseStub) )block; + +/** + * Setup a block to be called whenever OHHTTPStubs encounters a redirect request. + * + * @param block The block to call each time a redirect request is being stubbed by OHHTTPStubs. + * Set it to `nil` to do nothing. Defaults is `nil`. + */ ++(void)onStubRedirectResponse:( nullable void(^)(NSURLRequest* request, NSURLRequest* redirectRequest, id stub, OHHTTPStubsResponse* responseStub) )block; + +/** + * Setup a block to be called each time a stub finishes. Useful if stubs take an insignificant amount + * of time to execute (due to low bandwidth or delayed response time). This block may also be called + * if there are errors generated by OHHTTPStubs in the course of executing a network request. + * + * @param block The block to call each time a request is finished being stubbed by OHHTTPStubs. + * Set it to `nil` to do nothing. Defaults is `nil`. + */ ++(void)afterStubFinish:( nullable void(^)(NSURLRequest* request, id stub, OHHTTPStubsResponse* responseStub, NSError *error) )block; + +/** + * Setup a block to be called whenever OHHTTPStubs encounters a missing stub. + * + * @param block The block to call each time no stub for a request can be found. + * Set it to `nil` to do nothing. Defaults is `nil`. + */ ++(void)onStubMissing:( nullable void(^)(NSURLRequest* request) )block; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m new file mode 100644 index 0000000..3a0eaf8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m @@ -0,0 +1,658 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + +#if ! __has_feature(objc_arc) +#error This file is expected to be compiled with ARC turned ON +#endif + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import "OHHTTPStubs.h" + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Types & Constants + +@interface OHHTTPStubsProtocol : NSURLProtocol @end + +static NSTimeInterval const kSlotTime = 0.25; // Must be >0. We will send a chunk of the data from the stream each 'slotTime' seconds + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Private Interfaces + +@interface OHHTTPStubs() ++ (instancetype)sharedInstance; +@property(atomic, copy) NSMutableArray* stubDescriptors; +@property(atomic, assign) BOOL enabledState; +@property(atomic, copy, nullable) void (^onStubActivationBlock)(NSURLRequest*, id, OHHTTPStubsResponse*); +@property(atomic, copy, nullable) void (^onStubRedirectBlock)(NSURLRequest*, NSURLRequest*, id, OHHTTPStubsResponse*); +@property(atomic, copy, nullable) void (^afterStubFinishBlock)(NSURLRequest*, id, OHHTTPStubsResponse*, NSError*); +@property(atomic, copy, nullable) void (^onStubMissingBlock)(NSURLRequest*); +@end + +@interface OHHTTPStubsDescriptor : NSObject +@property(atomic, copy) OHHTTPStubsTestBlock testBlock; +@property(atomic, copy) OHHTTPStubsResponseBlock responseBlock; +@end + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - OHHTTPStubsDescriptor Implementation + +@implementation OHHTTPStubsDescriptor + +@synthesize name = _name; + ++(instancetype)stubDescriptorWithTestBlock:(OHHTTPStubsTestBlock)testBlock + responseBlock:(OHHTTPStubsResponseBlock)responseBlock +{ + OHHTTPStubsDescriptor* stub = [OHHTTPStubsDescriptor new]; + stub.testBlock = testBlock; + stub.responseBlock = responseBlock; + return stub; +} + +-(NSString*)description +{ + return [NSString stringWithFormat:@"<%@ %p : %@>", self.class, self, self.name]; +} + +@end + + + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - OHHTTPStubs Implementation + +@implementation OHHTTPStubs + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Singleton methods + ++ (instancetype)sharedInstance +{ + static OHHTTPStubs *sharedInstance = nil; + + static dispatch_once_t predicate; + dispatch_once(&predicate, ^{ + sharedInstance = [[self alloc] init]; + }); + + return sharedInstance; +} + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Setup & Teardown + ++ (void)initialize +{ + if (self == [OHHTTPStubs class]) + { + [self _setEnable:YES]; + } +} +- (instancetype)init +{ + self = [super init]; + if (self) + { + _stubDescriptors = [NSMutableArray array]; + _enabledState = YES; // assume initialize has already been run + } + return self; +} + +- (void)dealloc +{ + [self.class _setEnable:NO]; +} + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Public class methods + +#pragma mark > Adding & Removing stubs + ++(id)stubRequestsPassingTest:(OHHTTPStubsTestBlock)testBlock + withStubResponse:(OHHTTPStubsResponseBlock)responseBlock +{ + OHHTTPStubsDescriptor* stub = [OHHTTPStubsDescriptor stubDescriptorWithTestBlock:testBlock + responseBlock:responseBlock]; + [OHHTTPStubs.sharedInstance addStub:stub]; + return stub; +} + ++(BOOL)removeStub:(id)stubDesc +{ + return [OHHTTPStubs.sharedInstance removeStub:stubDesc]; +} + ++(void)removeAllStubs +{ + [OHHTTPStubs.sharedInstance removeAllStubs]; +} + +#pragma mark > Disabling & Re-Enabling stubs + ++(void)_setEnable:(BOOL)enable +{ + if (enable) + { + [NSURLProtocol registerClass:OHHTTPStubsProtocol.class]; + } + else + { + [NSURLProtocol unregisterClass:OHHTTPStubsProtocol.class]; + } +} + ++(void)setEnabled:(BOOL)enabled +{ + [OHHTTPStubs.sharedInstance setEnabled:enabled]; +} + ++(BOOL)isEnabled +{ + return OHHTTPStubs.sharedInstance.isEnabled; +} + +#if defined(__IPHONE_7_0) || defined(__MAC_10_9) ++ (void)setEnabled:(BOOL)enable forSessionConfiguration:(NSURLSessionConfiguration*)sessionConfig +{ + // Runtime check to make sure the API is available on this version + if ( [sessionConfig respondsToSelector:@selector(protocolClasses)] + && [sessionConfig respondsToSelector:@selector(setProtocolClasses:)]) + { + NSMutableArray * urlProtocolClasses = [NSMutableArray arrayWithArray:sessionConfig.protocolClasses]; + Class protoCls = OHHTTPStubsProtocol.class; + if (enable && ![urlProtocolClasses containsObject:protoCls]) + { + [urlProtocolClasses insertObject:protoCls atIndex:0]; + } + else if (!enable && [urlProtocolClasses containsObject:protoCls]) + { + [urlProtocolClasses removeObject:protoCls]; + } + sessionConfig.protocolClasses = urlProtocolClasses; + } + else + { + NSLog(@"[OHHTTPStubs] %@ is only available when running on iOS7+/OSX9+. " + @"Use conditions like 'if ([NSURLSessionConfiguration class])' to only call " + @"this method if the user is running iOS7+/OSX9+.", NSStringFromSelector(_cmd)); + } +} + ++ (BOOL)isEnabledForSessionConfiguration:(NSURLSessionConfiguration *)sessionConfig +{ + // Runtime check to make sure the API is available on this version + if ( [sessionConfig respondsToSelector:@selector(protocolClasses)] + && [sessionConfig respondsToSelector:@selector(setProtocolClasses:)]) + { + NSMutableArray * urlProtocolClasses = [NSMutableArray arrayWithArray:sessionConfig.protocolClasses]; + Class protoCls = OHHTTPStubsProtocol.class; + return [urlProtocolClasses containsObject:protoCls]; + } + else + { + NSLog(@"[OHHTTPStubs] %@ is only available when running on iOS7+/OSX9+. " + @"Use conditions like 'if ([NSURLSessionConfiguration class])' to only call " + @"this method if the user is running iOS7+/OSX9+.", NSStringFromSelector(_cmd)); + return NO; + } +} +#endif + +#pragma mark > Debug Methods + ++(NSArray*)allStubs +{ + return [OHHTTPStubs.sharedInstance stubDescriptors]; +} + ++(void)onStubActivation:( nullable void(^)(NSURLRequest* request, id stub, OHHTTPStubsResponse* responseStub) )block +{ + [OHHTTPStubs.sharedInstance setOnStubActivationBlock:block]; +} + ++(void)onStubRedirectResponse:( nullable void(^)(NSURLRequest* request, NSURLRequest* redirectRequest, id stub, OHHTTPStubsResponse* responseStub) )block +{ + [OHHTTPStubs.sharedInstance setOnStubRedirectBlock:block]; +} + ++(void)afterStubFinish:( nullable void(^)(NSURLRequest* request, id stub, OHHTTPStubsResponse* responseStub, NSError* error) )block +{ + [OHHTTPStubs.sharedInstance setAfterStubFinishBlock:block]; +} + ++(void)onStubMissing:( nullable void(^)(NSURLRequest* request) )block +{ + [OHHTTPStubs.sharedInstance setOnStubMissingBlock:block]; +} + + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Private instance methods + +-(BOOL)isEnabled +{ + BOOL enabled = NO; + @synchronized(self) + { + enabled = _enabledState; + } + return enabled; +} + +-(void)setEnabled:(BOOL)enable +{ + @synchronized(self) + { + _enabledState = enable; + [self.class _setEnable:_enabledState]; + } +} + +-(void)addStub:(OHHTTPStubsDescriptor*)stubDesc +{ + @synchronized(_stubDescriptors) + { + [_stubDescriptors addObject:stubDesc]; + } +} + +-(BOOL)removeStub:(id)stubDesc +{ + BOOL handlerFound = NO; + @synchronized(_stubDescriptors) + { + handlerFound = [_stubDescriptors containsObject:stubDesc]; + [_stubDescriptors removeObject:stubDesc]; + } + return handlerFound; +} + +-(void)removeAllStubs +{ + @synchronized(_stubDescriptors) + { + [_stubDescriptors removeAllObjects]; + } +} + +- (OHHTTPStubsDescriptor*)firstStubPassingTestForRequest:(NSURLRequest*)request +{ + OHHTTPStubsDescriptor* foundStub = nil; + @synchronized(_stubDescriptors) + { + for(OHHTTPStubsDescriptor* stub in _stubDescriptors.reverseObjectEnumerator) + { + if (stub.testBlock(request)) + { + foundStub = stub; + break; + } + } + } + return foundStub; +} + +@end + + + + + + + + + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Private Protocol Class + +@interface OHHTTPStubsProtocol() +@property(assign) BOOL stopped; +@property(strong) OHHTTPStubsDescriptor* stub; +@property(assign) CFRunLoopRef clientRunLoop; +- (void)executeOnClientRunLoopAfterDelay:(NSTimeInterval)delayInSeconds block:(dispatch_block_t)block; +@end + +@implementation OHHTTPStubsProtocol + ++ (BOOL)canInitWithRequest:(NSURLRequest *)request +{ + BOOL found = ([OHHTTPStubs.sharedInstance firstStubPassingTestForRequest:request] != nil); + if (!found && OHHTTPStubs.sharedInstance.onStubMissingBlock) { + OHHTTPStubs.sharedInstance.onStubMissingBlock(request); + } + return found; +} + +- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)response client:(id)client +{ + // Make super sure that we never use a cached response. + OHHTTPStubsProtocol* proto = [super initWithRequest:request cachedResponse:nil client:client]; + proto.stub = [OHHTTPStubs.sharedInstance firstStubPassingTestForRequest:request]; + return proto; +} + ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request +{ + return request; +} + +- (NSCachedURLResponse *)cachedResponse +{ + return nil; +} + +/** Drop certain headers in accordance with + * https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders + */ +- (NSMutableURLRequest *)clearAuthHeadersForRequest:(NSMutableURLRequest *)request { + NSArray* authHeadersToRemove = @[ + @"Authorization", + @"Connection", + @"Host", + @"Proxy-Authenticate", + @"Proxy-Authorization", + @"WWW-Authenticate" + ]; + for (NSString* header in authHeadersToRemove) { + [request setValue:nil forHTTPHeaderField:header]; + } + return request; +} + +- (void)startLoading +{ + self.clientRunLoop = CFRunLoopGetCurrent(); + NSURLRequest* request = self.request; + id client = self.client; + + if (!self.stub) + { + NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys: + @"It seems like the stub has been removed BEFORE the response had time to be sent.", + NSLocalizedFailureReasonErrorKey, + @"For more info, see https://github.com/AliSoftware/OHHTTPStubs/wiki/OHHTTPStubs-and-asynchronous-tests", + NSLocalizedRecoverySuggestionErrorKey, + request.URL, // Stop right here if request.URL is nil + NSURLErrorFailingURLErrorKey, + nil]; + NSError* error = [NSError errorWithDomain:@"OHHTTPStubs" code:500 userInfo:userInfo]; + [client URLProtocol:self didFailWithError:error]; + if (OHHTTPStubs.sharedInstance.afterStubFinishBlock) + { + OHHTTPStubs.sharedInstance.afterStubFinishBlock(request, self.stub, nil, error); + } + return; + } + + OHHTTPStubsResponse* responseStub = self.stub.responseBlock(request); + + if (OHHTTPStubs.sharedInstance.onStubActivationBlock) + { + OHHTTPStubs.sharedInstance.onStubActivationBlock(request, self.stub, responseStub); + } + + if (responseStub.error == nil) + { + NSHTTPURLResponse* urlResponse = [[NSHTTPURLResponse alloc] initWithURL:request.URL + statusCode:responseStub.statusCode + HTTPVersion:@"HTTP/1.1" + headerFields:responseStub.httpHeaders]; + + // Cookies handling + if (request.HTTPShouldHandleCookies && request.URL) + { + NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseStub.httpHeaders forURL:request.URL]; + if (cookies) + { + [NSHTTPCookieStorage.sharedHTTPCookieStorage setCookies:cookies forURL:request.URL mainDocumentURL:request.mainDocumentURL]; + } + } + + + NSString* redirectLocation = (responseStub.httpHeaders)[@"Location"]; + NSURL* redirectLocationURL; + if (redirectLocation) + { + redirectLocationURL = [NSURL URLWithString:redirectLocation]; + } + else + { + redirectLocationURL = nil; + } + [self executeOnClientRunLoopAfterDelay:responseStub.requestTime block:^{ + if (!self.stopped) + { + // Notify if a redirection occurred + if (((responseStub.statusCode > 300) && (responseStub.statusCode < 400)) && redirectLocationURL) + { + NSURLRequest *redirectRequest; + NSMutableURLRequest *mReq; + + switch (responseStub.statusCode) + { + case 301: + case 302: + case 307: + case 308: { + //Preserve the original request method and body, and set the new location URL + mReq = [self.request mutableCopy]; + [mReq setURL:redirectLocationURL]; + + mReq = [self clearAuthHeadersForRequest:mReq]; + + redirectRequest = (NSURLRequest*)[mReq copy]; + break; + } + default: + redirectRequest = [NSURLRequest requestWithURL:redirectLocationURL]; + break; + } + + [client URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:urlResponse]; + if (OHHTTPStubs.sharedInstance.onStubRedirectBlock) + { + OHHTTPStubs.sharedInstance.onStubRedirectBlock(request, redirectRequest, self.stub, responseStub); + } + } + + // Send the response (even for redirections) + [client URLProtocol:self didReceiveResponse:urlResponse cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + if(responseStub.inputStream.streamStatus == NSStreamStatusNotOpen) + { + [responseStub.inputStream open]; + } + [self streamDataForClient:client + withStubResponse:responseStub + completion:^(NSError * error) + { + [responseStub.inputStream close]; + NSError *blockError = nil; + if (error==nil) + { + [client URLProtocolDidFinishLoading:self]; + } + else + { + [client URLProtocol:self didFailWithError:responseStub.error]; + blockError = responseStub.error; + } + if (OHHTTPStubs.sharedInstance.afterStubFinishBlock) + { + OHHTTPStubs.sharedInstance.afterStubFinishBlock(request, self.stub, responseStub, blockError); + } + }]; + } + }]; + } else { + // Send the canned error + [self executeOnClientRunLoopAfterDelay:responseStub.responseTime block:^{ + if (!self.stopped) + { + [client URLProtocol:self didFailWithError:responseStub.error]; + if (OHHTTPStubs.sharedInstance.afterStubFinishBlock) + { + OHHTTPStubs.sharedInstance.afterStubFinishBlock(request, self.stub, responseStub, responseStub.error); + } + } + }]; + } +} + +- (void)stopLoading +{ + self.stopped = YES; +} + +typedef struct { + NSTimeInterval slotTime; + double chunkSizePerSlot; + double cumulativeChunkSize; +} OHHTTPStubsStreamTimingInfo; + +- (void)streamDataForClient:(id)client + withStubResponse:(OHHTTPStubsResponse*)stubResponse + completion:(void(^)(NSError * error))completion +{ + if (!self.stopped) + { + if ((stubResponse.dataSize>0) && stubResponse.inputStream.hasBytesAvailable) + { + // Compute timing data once and for all for this stub + + OHHTTPStubsStreamTimingInfo timingInfo = { + .slotTime = kSlotTime, // Must be >0. We will send a chunk of data from the stream each 'slotTime' seconds + .cumulativeChunkSize = 0 + }; + + if(stubResponse.responseTime < 0) + { + // Bytes send each 'slotTime' seconds = Speed in KB/s * 1000 * slotTime in seconds + timingInfo.chunkSizePerSlot = (fabs(stubResponse.responseTime) * 1000) * timingInfo.slotTime; + } + else if (stubResponse.responseTime < kSlotTime) // includes case when responseTime == 0 + { + // We want to send the whole data quicker than the slotTime, so send it all in one chunk. + timingInfo.chunkSizePerSlot = stubResponse.dataSize; + timingInfo.slotTime = stubResponse.responseTime; + } + else + { + // Bytes send each 'slotTime' seconds = (Whole size in bytes / response time) * slotTime = speed in bps * slotTime in seconds + timingInfo.chunkSizePerSlot = ((stubResponse.dataSize/stubResponse.responseTime) * timingInfo.slotTime); + } + + [self streamDataForClient:client + fromStream:stubResponse.inputStream + timingInfo:timingInfo + completion:completion]; + } + else + { + [self executeOnClientRunLoopAfterDelay:stubResponse.responseTime block:^{ + if (completion && !self.stopped) + { + completion(nil); + } + }]; + } + } +} + +- (void) streamDataForClient:(id)client + fromStream:(NSInputStream*)inputStream + timingInfo:(OHHTTPStubsStreamTimingInfo)timingInfo + completion:(void(^)(NSError * error))completion +{ + NSParameterAssert(timingInfo.chunkSizePerSlot > 0); + + if (inputStream.hasBytesAvailable && (!self.stopped)) + { + // This is needed in case we computed a non-integer chunkSizePerSlot, to avoid cumulative errors + double cumulativeChunkSizeAfterRead = timingInfo.cumulativeChunkSize + timingInfo.chunkSizePerSlot; + NSUInteger chunkSizeToRead = floor(cumulativeChunkSizeAfterRead) - floor(timingInfo.cumulativeChunkSize); + timingInfo.cumulativeChunkSize = cumulativeChunkSizeAfterRead; + + if (chunkSizeToRead == 0) + { + // Nothing to read at this pass, but probably later + [self executeOnClientRunLoopAfterDelay:timingInfo.slotTime block:^{ + [self streamDataForClient:client fromStream:inputStream + timingInfo:timingInfo completion:completion]; + }]; + } else { + uint8_t* buffer = (uint8_t*)malloc(sizeof(uint8_t)*chunkSizeToRead); + NSInteger bytesRead = [inputStream read:buffer maxLength:chunkSizeToRead]; + if (bytesRead > 0) + { + NSData * data = [NSData dataWithBytes:buffer length:bytesRead]; + // Wait for 'slotTime' seconds before sending the chunk. + // If bytesRead < chunkSizePerSlot (because we are near the EOF), adjust slotTime proportionally to the bytes remaining + [self executeOnClientRunLoopAfterDelay:((double)bytesRead / (double)chunkSizeToRead) * timingInfo.slotTime block:^{ + [client URLProtocol:self didLoadData:data]; + [self streamDataForClient:client fromStream:inputStream + timingInfo:timingInfo completion:completion]; + }]; + } + else + { + if (completion) + { + // Note: We may also arrive here with no error if we were just at the end of the stream (EOF) + // In that case, hasBytesAvailable did return YES (because at the limit of OEF) but nothing were read (because EOF) + // But then in that case inputStream.streamError will be nil so that's cool, we won't return an error anyway + completion(inputStream.streamError); + } + } + free(buffer); + } + } + else + { + if (completion) + { + completion(nil); + } + } +} + +///////////////////////////////////////////// +// Delayed execution utility methods +///////////////////////////////////////////// + +- (void)executeOnClientRunLoopAfterDelay:(NSTimeInterval)delayInSeconds block:(dispatch_block_t)block +{ + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + CFRunLoopPerformBlock(self.clientRunLoop, kCFRunLoopDefaultMode, block); + CFRunLoopWakeUp(self.clientRunLoop); + }); +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h new file mode 100644 index 0000000..f9995fc --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h @@ -0,0 +1,301 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import + +#import "Compatibility.h" + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Defines & Constants + +// Non-standard download speeds +extern const double +OHHTTPStubsDownloadSpeed1KBPS, // 1.0 KB per second +OHHTTPStubsDownloadSpeedSLOW; // 1.5 KB per second + +// Standard download speeds. +extern const double +OHHTTPStubsDownloadSpeedGPRS, +OHHTTPStubsDownloadSpeedEDGE, +OHHTTPStubsDownloadSpeed3G, +OHHTTPStubsDownloadSpeed3GPlus, +OHHTTPStubsDownloadSpeedWifi; + + +NS_ASSUME_NONNULL_BEGIN + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Interface + +/** + * Stubs Response. This describes a stubbed response to be returned by the URL Loading System, + * including its HTTP headers, body, statusCode and response time. + */ +@interface OHHTTPStubsResponse : NSObject + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Properties + +/** + * The headers to use for the fake response + */ +@property(nonatomic, strong, nullable) NSDictionary* httpHeaders; +/** + * The HTTP status code to use for the fake response + */ +@property(nonatomic, assign) int statusCode; +/** + * The inputStream used when sending the response. + * @note You generally don't manipulate this directly. + */ +@property(nonatomic, strong, nullable) NSInputStream* inputStream; +/** + * The size of the fake response body, in bytes. + */ +@property(nonatomic, assign) unsigned long long dataSize; +/** + * The duration to wait before faking receiving the response headers. + * + * Defaults to 0.0. + */ +@property(nonatomic, assign) NSTimeInterval requestTime; +/** + * The duration to use to send the fake response body. + * + * @note if responseTime<0, it is interpreted as a download speed in KBps ( -200 => 200KB/s ) + */ +@property(nonatomic, assign) NSTimeInterval responseTime; +/** + * The fake error to generate to simulate a network error. + * + * If `error` is non-`nil`, the request will result in a failure and no response will be sent. + */ +@property(nonatomic, strong, nullable) NSError* error; + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Commodity Constructors +/*! @name Commodity */ + +/* -------------------------------------------------------------------------- */ +#pragma mark > Building response from NSData + +/** + * Builds a response given raw data. + * + * @note Internally calls `-initWithInputStream:dataSize:statusCode:headers:` with and inputStream built from the NSData. + * + * @param data The raw data to return in the response + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + */ ++(instancetype)responseWithData:(NSData*)data + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders; + + +/* -------------------------------------------------------------------------- */ +#pragma mark > Building response from a file + +/** + * Builds a response given a file path, the status code and headers. + * + * @param filePath The file path that contains the response body to return. + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note It is encouraged to use the OHPathHelpers functions & macros to build + * the filePath parameter easily + */ ++(instancetype)responseWithFileAtPath:(NSString *)filePath + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders; + + +/** + * Builds a response given a URL, the status code, and headers. + * + * @param fileURL The URL for the data to return in the response + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note This method applies only to URLs that represent file system resources + */ ++(instancetype)responseWithFileURL:(NSURL *)fileURL + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders; + +/* -------------------------------------------------------------------------- */ +#pragma mark > Building an error response + +/** + * Builds a response that corresponds to the given error + * + * @param error The error to use in the stubbed response. + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note For example you could use an error like `[NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:nil]` + */ ++(instancetype)responseWithError:(NSError*)error; + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Commotidy Setters + +/** + * Set the `responseTime` of the `OHHTTPStubsResponse` and return `self`. Useful for chaining method calls. + * + * _Usage example:_ + *
return [[OHHTTPStubsResponse responseWithData:data statusCode:200 headers:nil] responseTime:5.0];
+ * + * @param responseTime If positive, the amount of time used to send the entire response. + * If negative, the rate in KB/s at which to send the response data. + * Useful to simulate slow networks for example. You may use the + * _OHHTTPStubsDownloadSpeed…_ constants here. + * + * @return `self` (= the same `OHHTTPStubsResponse` that was the target of this method). + * Returning `self` is useful for chaining method calls. + */ +-(instancetype)responseTime:(NSTimeInterval)responseTime; + +/** + * Set both the `requestTime` and the `responseTime` of the `OHHTTPStubsResponse` at once. + * Useful for chaining method calls. + * + * _Usage example:_ + *
return [[OHHTTPStubsResponse responseWithData:data statusCode:200 headers:nil]
+ *            requestTime:1.0 responseTime:5.0];
+ * + * @param requestTime The time to wait before the response begins to send. This value must be greater than or equal to zero. + * @param responseTime If positive, the amount of time used to send the entire response. + * If negative, the rate in KB/s at which to send the response data. + * Useful to simulate slow networks for example. You may use the + * _OHHTTPStubsDownloadSpeed…_ constants here. + * + * @return `self` (= the same `OHHTTPStubsResponse` that was the target of this method). Useful for chaining method calls. + */ +-(instancetype)requestTime:(NSTimeInterval)requestTime responseTime:(NSTimeInterval)responseTime; + + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Initializers +/*! @name Initializers */ + +/** + * Designated empty initializer + * + * @return An empty `OHHTTPStubsResponse` on which you need to set either an error or a statusCode, httpHeaders, inputStream and dataSize. + * + * @note This is not recommended to use this method directly. You should use `initWithInputStream:dataSize:statusCode:headers:` instead. + */ +-(instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Designed initializer. Initialize a response with the given input stream, dataSize, + * statusCode and headers. + * + * @param inputStream The input stream that will provide the data to return in the response + * @param dataSize The size of the data in the stream. + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note You will probably never need to call this method yourself. Prefer the other initializers (that will call this method eventually) + */ +-(instancetype)initWithInputStream:(NSInputStream*)inputStream + dataSize:(unsigned long long)dataSize + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders NS_DESIGNATED_INITIALIZER; + + +/** + * Initialize a response with a given file path, statusCode and headers. + * + * @param filePath The file path of the data to return in the response + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note This method simply builds the NSInputStream, compute the file size, and then call `-initWithInputStream:dataSize:statusCode:headers:` + */ +-(instancetype)initWithFileAtPath:(NSString*)filePath + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders; + + +/** + * Initialize a response with a given URL, statusCode and headers. + * + * @param fileURL The URL for the data to return in the response + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note This method applies only to URLs that represent file system resources + */ +-(instancetype)initWithFileURL:(NSURL *)fileURL + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders; + +/** + * Initialize a response with the given data, statusCode and headers. + * + * @param data The raw data to return in the response + * @param statusCode The HTTP Status Code to use in the response + * @param httpHeaders The HTTP Headers to return in the response + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + */ +-(instancetype)initWithData:(NSData*)data + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders; + + +/** + * Designed initializer. Initialize a response with the given error. + * + * @param error The error to use in the stubbed response. + * + * @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub + * + * @note For example you could use an error like `[NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:nil]` + */ +-(instancetype)initWithError:(NSError*)error NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m new file mode 100644 index 0000000..c5d2a70 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m @@ -0,0 +1,220 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + +#if ! __has_feature(objc_arc) +#error This file is expected to be compiled with ARC turned ON +#endif + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Imports + +#import "OHHTTPStubsResponse.h" + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Defines & Constants +const double OHHTTPStubsDownloadSpeed1KBPS =- 8 / 8; // kbps -> KB/s +const double OHHTTPStubsDownloadSpeedSLOW =- 12 / 8; // kbps -> KB/s +const double OHHTTPStubsDownloadSpeedGPRS =- 56 / 8; // kbps -> KB/s +const double OHHTTPStubsDownloadSpeedEDGE =- 128 / 8; // kbps -> KB/s +const double OHHTTPStubsDownloadSpeed3G =- 3200 / 8; // kbps -> KB/s +const double OHHTTPStubsDownloadSpeed3GPlus =- 7200 / 8; // kbps -> KB/s +const double OHHTTPStubsDownloadSpeedWifi =- 12000 / 8; // kbps -> KB/s + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Implementation + +@implementation OHHTTPStubsResponse + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Commodity Constructors + + +#pragma mark > Building response from NSData + ++(instancetype)responseWithData:(NSData*)data + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders +{ + OHHTTPStubsResponse* response = [[self alloc] initWithData:data + statusCode:statusCode + headers:httpHeaders]; + return response; +} + + +#pragma mark > Building response from a file + ++(instancetype)responseWithFileAtPath:(NSString *)filePath + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders +{ + OHHTTPStubsResponse* response = [[self alloc] initWithFileAtPath:filePath + statusCode:statusCode + headers:httpHeaders]; + return response; +} + ++(instancetype)responseWithFileURL:(NSURL *)fileURL + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders +{ + OHHTTPStubsResponse* response = [[self alloc] initWithFileURL:fileURL + statusCode:statusCode + headers:httpHeaders]; + return response; +} + +#pragma mark > Building an error response + ++(instancetype)responseWithError:(NSError*)error +{ + OHHTTPStubsResponse* response = [[self alloc] initWithError:error]; + return response; +} + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Commotidy Setters + +-(instancetype)responseTime:(NSTimeInterval)responseTime +{ + _responseTime = responseTime; + return self; +} + +-(instancetype)requestTime:(NSTimeInterval)requestTime responseTime:(NSTimeInterval)responseTime +{ + _requestTime = requestTime; + _responseTime = responseTime; + return self; +} + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Initializers + +-(instancetype)init +{ + self = [super init]; + return self; +} + +-(instancetype)initWithInputStream:(NSInputStream*)inputStream + dataSize:(unsigned long long)dataSize + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders +{ + self = [super init]; + if (self) + { + _inputStream = inputStream; + _dataSize = dataSize; + _statusCode = statusCode; + NSMutableDictionary * headers = [NSMutableDictionary dictionaryWithDictionary:httpHeaders]; + static NSString *const ContentLengthHeader = @"Content-Length"; + if (!headers[ContentLengthHeader]) + { + headers[ContentLengthHeader] = [NSString stringWithFormat:@"%llu",_dataSize]; + } + _httpHeaders = [NSDictionary dictionaryWithDictionary:headers]; + } + return self; +} + +-(instancetype)initWithFileAtPath:(NSString*)filePath + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders +{ + NSURL *fileURL = filePath ? [NSURL fileURLWithPath:filePath] : nil; + self = [self initWithFileURL:fileURL + statusCode:statusCode + headers:httpHeaders]; + return self; +} + +-(instancetype)initWithFileURL:(NSURL *)fileURL + statusCode:(int)statusCode + headers:(nullable NSDictionary *)httpHeaders { + if (!fileURL) { + NSLog(@"%s: nil file path. Returning empty data", __PRETTY_FUNCTION__); + return [self initWithInputStream:[NSInputStream inputStreamWithData:[NSData data]] + dataSize:0 + statusCode:statusCode + headers:httpHeaders]; + } + + // [NSURL -isFileURL] is only available on iOS 8+ + NSAssert([fileURL.scheme isEqualToString:NSURLFileScheme], @"%s: Only file URLs may be passed to this method.",__PRETTY_FUNCTION__); + + NSNumber *fileSize; + NSError *error; + const BOOL success __unused = [fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:&error]; + + NSAssert(success && fileSize, @"%s Couldn't get the file size for URL. \ +The URL was: %@. \ +The operation to retrieve the file size was %@. \ +The error associated with that operation was: %@", + __PRETTY_FUNCTION__, fileURL, success ? @"successful" : @"unsuccessful", error); + + return [self initWithInputStream:[NSInputStream inputStreamWithURL:fileURL] + dataSize:[fileSize unsignedLongLongValue] + statusCode:statusCode + headers:httpHeaders]; +} + +-(instancetype)initWithData:(NSData*)data + statusCode:(int)statusCode + headers:(nullable NSDictionary*)httpHeaders +{ + NSInputStream* inputStream = [NSInputStream inputStreamWithData:data?:[NSData data]]; + self = [self initWithInputStream:inputStream + dataSize:data.length + statusCode:statusCode + headers:httpHeaders]; + return self; +} + +-(instancetype)initWithError:(NSError*)error +{ + self = [super init]; + if (self) { + _error = error; + } + return self; +} + +-(NSString*)debugDescription +{ + return [NSString stringWithFormat:@"<%@ %p requestTime:%f responseTime:%f status:%d dataSize:%llu>", + self.class, self, self.requestTime, self.responseTime, self.statusCode, self.dataSize]; +} + +//////////////////////////////////////////////////////////////////////////////// +#pragma mark - Accessors + +-(void)setRequestTime:(NSTimeInterval)requestTime +{ + NSAssert(requestTime >= 0, @"Invalid Request Time (%f) for OHHTTPStubResponse. Request time must be greater than or equal to zero",requestTime); + _requestTime = requestTime; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h new file mode 100644 index 0000000..d924df4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h @@ -0,0 +1,87 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +#import + +#import "Compatibility.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Useful function to build a path given a file name and a class. + * + * @param fileName The name of the file to get the path to, including file extension + * @param inBundleForClass The class of the caller, used to determine the current bundle + * in which the file is supposed to be located. + * You should typically pass `self.class` (ObjC) or + * `self.dynamicType` (Swift < 3.0) or `type(of: self)` (Swift >= 3.0) when calling this function. + * + * @return The path of the given file in the same bundle as the inBundleForClass class + */ +NSString* __nullable OHPathForFile(NSString* fileName, Class inBundleForClass); + +/** + * Useful function to build a path given a file name and a bundle. + * + * @param fileName The name of the file to get the path to, including file extension + * @param bundle The bundle in which the file is supposed to be located. + * This parameter can't be null. + * + * @return The path of the given file in given bundle + * + * @note You should avoid using `[NSBundle mainBundle]` for the `bundle` parameter, + * as in the context of Unit Tests, this points to the Simulator's bundle, + * not the bundle of the app under test. That's why `nil` is not an acceptable + * value (so you won't expect it to default to the `mainBundle`). + * You should use `[NSBundle bundleForClass:]` instead. + */ +NSString* __nullable OHPathForFileInBundle(NSString* fileName, NSBundle* bundle); + +/** + * Useful function to build a path to a file in the Documents's directory in the + * app sandbox, used by iTunes File Sharing for example. + * + * @param fileName The name of the file to get the path to, including file extension + * + * @return The path of the file in the Documents directory in your App Sandbox + */ +NSString* __nullable OHPathForFileInDocumentsDir(NSString* fileName); + + + +/** + * Useful function to build an NSBundle located in the application's resources simply from its name + * + * @param bundleBasename The base name, without extension (extension is assumed to be ".bundle"). + * @param inBundleForClass The class of the caller, used to determine the current bundle + * in which the file is supposed to be located. + * You should typically pass `self.class` (ObjC) or + * `self.dynamicType` (Swift) when calling this function. + * + * @return The NSBundle object representing the bundle with the given basename located in your application's resources. + */ +NSBundle* __nullable OHResourceBundle(NSString* bundleBasename, Class inBundleForClass); + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m new file mode 100644 index 0000000..89d1e05 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m @@ -0,0 +1,52 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + + +#import "OHPathHelpers.h" + +NSString* __nullable OHPathForFile(NSString* fileName, Class inBundleForClass) +{ + NSBundle* bundle = [NSBundle bundleForClass:inBundleForClass]; + return OHPathForFileInBundle(fileName, bundle); +} + +NSString* __nullable OHPathForFileInBundle(NSString* fileName, NSBundle* bundle) +{ + return [bundle pathForResource:[fileName stringByDeletingPathExtension] + ofType:[fileName pathExtension]]; +} + +NSString* __nullable OHPathForFileInDocumentsDir(NSString* fileName) +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *basePath = (paths.count > 0) ? paths[0] : nil; + return [basePath stringByAppendingPathComponent:fileName]; +} + +NSBundle* __nullable OHResourceBundle(NSString* bundleBasename, Class inBundleForClass) +{ + NSBundle* classBundle = [NSBundle bundleForClass:inBundleForClass]; + return [NSBundle bundleWithPath:[classBundle pathForResource:bundleBasename + ofType:@"bundle"]]; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift new file mode 100644 index 0000000..7d9236e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift @@ -0,0 +1,478 @@ +/*********************************************************************************** + * + * Copyright (c) 2012 Olivier Halligon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + ***********************************************************************************/ + +/** + * Swift Helpers + */ + + +#if !swift(>=3.0) + extension OHHTTPStubs { + private class func stubRequests(passingTest passingTest: OHHTTPStubsTestBlock, withStubResponse: OHHTTPStubsResponseBlock) -> OHHTTPStubsDescriptor { + return stubRequestsPassingTest(passingTest, withStubResponse: withStubResponse) + } + } + + extension NSURLRequest { + var httpMethod: String? { return HTTPMethod } + var url: NSURL? { return URL } + } + + extension NSURLComponents { + private convenience init?(url: NSURL, resolvingAgainstBaseURL: Bool) { + self.init(URL: url, resolvingAgainstBaseURL: resolvingAgainstBaseURL) + } + } + + private typealias URLRequest = NSURLRequest + + extension URLRequest { + private func value(forHTTPHeaderField key: String) -> String? { + return valueForHTTPHeaderField(key) + } + } + + extension String { + private func contains(string: String) -> Bool { + return rangeOfString(string) != nil + } + } +#else + extension URLRequest { + public var ohhttpStubs_httpBody: Data? { + return (self as NSURLRequest).ohhttpStubs_HTTPBody() + } + } +#endif + + +// MARK: Syntaxic Sugar for OHHTTPStubs + +/** + * Helper to return a `OHHTTPStubsResponse` given a fixture path, status code and optional headers. + * + * - Parameter filePath: the path of the file fixture to use for the response + * - Parameter status: the status code to use for the response + * - Parameter headers: the HTTP headers to use for the response + * + * - Returns: The `OHHTTPStubsResponse` instance that will stub with the given status code + * & headers, and use the file content as the response body. + */ +#if swift(>=3.0) + public func fixture(filePath: String, status: Int32 = 200, headers: [AnyHashable: Any]?) -> OHHTTPStubsResponse { + return OHHTTPStubsResponse(fileAtPath: filePath, statusCode: status, headers: headers) + } +#else + public func fixture(filePath: String, status: Int32 = 200, headers: [NSObject: AnyObject]?) -> OHHTTPStubsResponse { + return OHHTTPStubsResponse(fileAtPath: filePath, statusCode: status, headers: headers) + } +#endif + +/** + * Helper to call the stubbing function in a more concise way? + * + * - Parameter condition: the matcher block that determine if the request will be stubbed + * - Parameter response: the stub reponse to use if the request is stubbed + * + * - Returns: The opaque `OHHTTPStubsDescriptor` that uniquely identifies the stub + * and can be later used to remove it with `removeStub:` + */ +#if swift(>=3.0) + @discardableResult + public func stub(condition: @escaping OHHTTPStubsTestBlock, response: @escaping OHHTTPStubsResponseBlock) -> OHHTTPStubsDescriptor { + return OHHTTPStubs.stubRequests(passingTest: condition, withStubResponse: response) + } +#else + public func stub(condition: OHHTTPStubsTestBlock, response: OHHTTPStubsResponseBlock) -> OHHTTPStubsDescriptor { + return OHHTTPStubs.stubRequests(passingTest: condition, withStubResponse: response) + } +#endif + + + +// MARK: Create OHHTTPStubsTestBlock matchers + +/** + * Matcher testing that the `NSURLRequest` is using the **GET** `HTTPMethod` + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * is using the GET method + */ +public func isMethodGET() -> OHHTTPStubsTestBlock { + return { $0.httpMethod == "GET" } +} + +/** + * Matcher testing that the `NSURLRequest` is using the **POST** `HTTPMethod` + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * is using the POST method + */ +public func isMethodPOST() -> OHHTTPStubsTestBlock { + return { $0.httpMethod == "POST" } +} + +/** + * Matcher testing that the `NSURLRequest` is using the **PUT** `HTTPMethod` + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * is using the PUT method + */ +public func isMethodPUT() -> OHHTTPStubsTestBlock { + return { $0.httpMethod == "PUT" } +} + +/** + * Matcher testing that the `NSURLRequest` is using the **PATCH** `HTTPMethod` + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * is using the PATCH method + */ +public func isMethodPATCH() -> OHHTTPStubsTestBlock { + return { $0.httpMethod == "PATCH" } +} + +/** + * Matcher testing that the `NSURLRequest` is using the **DELETE** `HTTPMethod` + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * is using the DELETE method + */ +public func isMethodDELETE() -> OHHTTPStubsTestBlock { + return { $0.httpMethod == "DELETE" } +} + +/** + * Matcher testing that the `NSURLRequest` is using the **HEAD** `HTTPMethod` + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * is using the HEAD method + */ +public func isMethodHEAD() -> OHHTTPStubsTestBlock { + return { $0.httpMethod == "HEAD" } +} + +/** + * Matcher for testing an `NSURLRequest`'s **absolute url string**. + * +* e.g. the absolute url string is `https://api.example.com/signin?user=foo&password=123#anchor` in `https://api.example.com/signin?user=foo&password=123#anchor` + * + * - Parameter url: The absolute url string to match + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * has the given absolute url + */ +public func isAbsoluteURLString(_ url: String) -> OHHTTPStubsTestBlock { + return { req in req.url?.absoluteString == url } +} + +/** + * Matcher for testing an `NSURLRequest`'s **scheme**. + * + * e.g. the scheme part is `https` in `https://api.example.com/signin` + * + * - Parameter scheme: The scheme to match + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * has the given scheme + */ +public func isScheme(_ scheme: String) -> OHHTTPStubsTestBlock { + precondition(!scheme.contains("://"), "The scheme part of an URL never contains '://'. Only use strings like 'https' for this value, and not things like 'https://'") + precondition(!scheme.contains("/"), "The scheme part of an URL never contains any slash. Only use strings like 'https' for this value, and not things like 'https://api.example.com/'") + return { req in req.url?.scheme == scheme } +} + +/** + * Matcher for testing an `NSURLRequest`'s **host**. + * + * e.g. the host part is `api.example.com` in `https://api.example.com/signin`. + * + * - Parameter host: The host to match (e.g. 'api.example.com') + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * has the given host + */ +public func isHost(_ host: String) -> OHHTTPStubsTestBlock { + precondition(!host.contains("/"), "The host part of an URL never contains any slash. Only use strings like 'api.example.com' for this value, and not things like 'https://api.example.com/'") + return { req in req.url?.host == host } +} + +/** + * Matcher for testing an `NSURLRequest`'s **path**. + * + * e.g. the path is `/signin` in `https://api.example.com/signin`. + * + * - Parameter path: The path to match + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request + * has exactly the given path + * + * - Note: URL paths are usually absolute and thus starts with a '/' (which you + * should include in the `path` parameter unless you're testing relative URLs) + */ +public func isPath(_ path: String) -> OHHTTPStubsTestBlock { + return { req in req.url?.path == path } +} + +private func getPath(_ req: URLRequest) -> String? { + #if swift(>=3.0) + return req.url?.path // In Swift 3, path is non-optional + #else + return req.url?.path + #endif +} +/** + * Matcher for testing the start of an `NSURLRequest`'s **path**. + * + * - Parameter path: The path to match + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request's + * path starts with the given string + * + * - Note: URL paths are usually absolute and thus starts with a '/' (which you + * should include in the `path` parameter unless you're testing relative URLs) + */ +public func pathStartsWith(_ path: String) -> OHHTTPStubsTestBlock { + return { req in getPath(req)?.hasPrefix(path) ?? false } +} + +/** + * Matcher for testing the end of an `NSURLRequest`'s **path**. + * + * - Parameter path: The path to match + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request's + * path ends with the given string + */ +public func pathEndsWith(_ path: String) -> OHHTTPStubsTestBlock { + return { req in getPath(req)?.hasSuffix(path) ?? false } +} + +/** + * Matcher for testing if the path of an `NSURLRequest` matches a RegEx. + * + * - Parameter regex: The Regular Expression we want the path to match + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request's + * path matches the given regular expression + * + * - Note: URL paths are usually absolute and thus starts with a '/' + */ +public func pathMatches(_ regex: NSRegularExpression) -> OHHTTPStubsTestBlock { + return { req in + guard let path = getPath(req) else { return false } + let range = NSRange(location: 0, length: path.utf16.count) + #if swift(>=3.0) + return regex.firstMatch(in: path, options: [], range: range) != nil + #else + return regex.firstMatchInString(path, options: [], range: range) != nil + #endif + } +} + +/** + * Matcher for testing if the path of an `NSURLRequest` matches a RegEx. + * + * - Parameter regexString: The Regular Expression string we want the path to match + * - Parameter options: The Regular Expression options to use. + * Defaults to no option. Common option includes e.g. `.caseInsensitive`. + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request's + * path matches the given regular expression + * + * - Note: This is a convenience function building an NSRegularExpression + * and calling pathMatches(…) with it + */ +#if swift(>=3.0) +public func pathMatches(_ regexString: String, options: NSRegularExpression.Options = []) -> OHHTTPStubsTestBlock { + guard let regex = try? NSRegularExpression(pattern: regexString, options: options) else { + return { _ in false } + } + return pathMatches(regex) +} +#else + public func pathMatches(_ regexString: String, options: NSRegularExpressionOptions = []) -> OHHTTPStubsTestBlock { + guard let regex = try? NSRegularExpression(pattern: regexString, options: options) else { + return { _ in false } + } + return pathMatches(regex) + } +#endif + +/** + * Matcher for testing an `NSURLRequest`'s **path extension**. + * + * - Parameter ext: The file extension to match (without the dot) + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds only if the request path + * ends with the given extension + */ +public func isExtension(_ ext: String) -> OHHTTPStubsTestBlock { + return { req in req.url?.pathExtension == ext } +} + +/** + * Matcher for testing an `NSURLRequest`'s **query parameters**. + * + * - Parameter params: The dictionary of query parameters to check the presence for + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that succeeds if the request contains + * the given query parameters with the given value. + * + * - Note: There is a difference between: + * (1) using `[q:""]`, which matches a query parameter "?q=" with an empty value, and + * (2) using `[q:nil]`, which matches a query parameter "?q" without a value at all + */ +@available(iOS 8.0, OSX 10.10, *) +public func containsQueryParams(_ params: [String:String?]) -> OHHTTPStubsTestBlock { + return { req in + if let url = req.url { + let comps = NSURLComponents(url: url, resolvingAgainstBaseURL: true) + if let queryItems = comps?.queryItems { + for (k,v) in params { + if queryItems.filter({ qi in qi.name == k && qi.value == v }).count == 0 { return false } + } + return true + } + } + return false + } +} + +/** + * Matcher testing that the `NSURLRequest` headers contain a specific key + * - Parameter name: the name of the key to search for in the `NSURLRequest`'s **allHTTPHeaderFields** property + * + * - Returns: a matcher that returns true if the `NSURLRequest`'s headers contain a value for the key name + */ +public func hasHeaderNamed(_ name: String) -> OHHTTPStubsTestBlock { + return { (req: URLRequest) -> Bool in + return req.value(forHTTPHeaderField: name) != nil + } +} + +/** + * Matcher testing that the `NSURLRequest` headers contain a specific key and the key's value is equal to the parameter value + * - Parameter name: the name of the key to search for in the `NSURLRequest`'s **allHTTPHeaderFields** property + * - Parameter value: the value to compare against the header's value + * + * - Returns: a matcher that returns true if the `NSURLRequest`'s headers contain a value for the key name and it's value + * is equal to the parameter value + */ +public func hasHeaderNamed(_ name: String, value: String) -> OHHTTPStubsTestBlock { + return { (req: URLRequest) -> Bool in + return req.value(forHTTPHeaderField: name) == value + } +} + +/** + * Matcher testing that the `NSURLRequest` body contain exactly specific data bytes + * - Parameter body: the Data bytes to expect + * + * - Returns: a matcher that returns true if the `NSURLRequest`'s body is exactly the same as the parameter value + */ +#if swift(>=3.0) + public func hasBody(_ body: Data) -> OHHTTPStubsTestBlock { + return { req in (req as NSURLRequest).ohhttpStubs_HTTPBody() == body } + } +#else + public func hasBody(_ body: NSData) -> OHHTTPStubsTestBlock { + return { req in req.OHHTTPStubs_HTTPBody() == body } + } +#endif + +/** + * Matcher testing that the `NSURLRequest` body contains a JSON object with the same keys and values + * - Parameter jsonObject: the JSON object to expect + * + * - Returns: a matcher that returns true if the `NSURLRequest`'s body contains a JSON object with the same keys and values as the parameter value + */ +#if swift(>=3.0) +public func hasJsonBody(_ jsonObject: [AnyHashable : Any]) -> OHHTTPStubsTestBlock { + return { req in + guard + let httpBody = req.ohhttpStubs_httpBody, + let jsonBody = (try? JSONSerialization.jsonObject(with: httpBody, options: [])) as? [AnyHashable : Any] + else { + return false + } + return NSDictionary(dictionary: jsonBody).isEqual(to: jsonObject) + } +} +#endif + +// MARK: Operators on OHHTTPStubsTestBlock + +/** + * Combine different `OHHTTPStubsTestBlock` matchers with an 'OR' operation. + * + * - Parameter lhs: the first matcher to test + * - Parameter rhs: the second matcher to test + * + * - Returns: a matcher (`OHHTTPStubsTestBlock`) that succeeds if either of the given matchers succeeds + */ +#if swift(>=3.0) + public func || (lhs: @escaping OHHTTPStubsTestBlock, rhs: @escaping OHHTTPStubsTestBlock) -> OHHTTPStubsTestBlock { + return { req in lhs(req) || rhs(req) } + } +#else + public func || (lhs: OHHTTPStubsTestBlock, rhs: OHHTTPStubsTestBlock) -> OHHTTPStubsTestBlock { + return { req in lhs(req) || rhs(req) } + } +#endif + +/** + * Combine different `OHHTTPStubsTestBlock` matchers with an 'AND' operation. + * + * - Parameter lhs: the first matcher to test + * - Parameter rhs: the second matcher to test + * + * - Returns: a matcher (`OHHTTPStubsTestBlock`) that only succeeds if both of the given matchers succeeds + */ +#if swift(>=3.0) + public func && (lhs: @escaping OHHTTPStubsTestBlock, rhs: @escaping OHHTTPStubsTestBlock) -> OHHTTPStubsTestBlock { + return { req in lhs(req) && rhs(req) } + } +#else + public func && (lhs: OHHTTPStubsTestBlock, rhs: OHHTTPStubsTestBlock) -> OHHTTPStubsTestBlock { + return { req in lhs(req) && rhs(req) } + } +#endif + +/** + * Create the opposite of a given `OHHTTPStubsTestBlock` matcher. + * + * - Parameter expr: the matcher to negate + * + * - Returns: a matcher (OHHTTPStubsTestBlock) that only succeeds if the expr matcher fails + */ +#if swift(>=3.0) + public prefix func ! (expr: @escaping OHHTTPStubsTestBlock) -> OHHTTPStubsTestBlock { + return { req in !expr(req) } + } +#else + public prefix func ! (expr: OHHTTPStubsTestBlock) -> OHHTTPStubsTestBlock { + return { req in !expr(req) } + } +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/README.md new file mode 100644 index 0000000..b76223f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/OHHTTPStubs/README.md @@ -0,0 +1,210 @@ +OHHTTPStubs +=========== + +[![Platform](http://cocoapod-badges.herokuapp.com/p/OHHTTPStubs/badge.png)](http://cocoadocs.org/docsets/OHHTTPStubs) +[![Version](http://cocoapod-badges.herokuapp.com/v/OHHTTPStubs/badge.png)](http://cocoadocs.org/docsets/OHHTTPStubs) +[![Carthage Swift 5.0](https://img.shields.io/badge/Carthage-Swift%205.0-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Build Status](https://travis-ci.org/AliSoftware/OHHTTPStubs.svg?branch=master)](https://travis-ci.org/AliSoftware/OHHTTPStubs) +[![Language: Swift-2.x/3.x/4.x/5.0](https://img.shields.io/badge/Swift-2.x%2F3.x%2F4.x%2F5.0-orange.svg)](https://swift.org) + +`OHHTTPStubs` is a library designed to stub your network requests very easily. It can help you: + +* test your apps with **fake network data** (stubbed from file) and **simulate slow networks**, to check your application behavior in bad network conditions +* write **unit tests** that use fake network data from your fixtures. + +It works with `NSURLConnection`, `NSURLSession`, `AFNetworking`, `Alamofire` or any networking framework that use Cocoa's URL Loading System. + +[Donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TRTU3UEWEHV92 "Donate") + +---- + +# Documentation & Usage Examples + +`OHHTTPStubs` headers are fully documented using Appledoc-like / Headerdoc-like comments in the header files. You can also [read the **online documentation** here](http://cocoadocs.org/docsets/OHHTTPStubs). + + +## Basic example + +
+In Objective-C + +```objc +[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { + return [request.URL.host isEqualToString:@"mywebservice.com"]; +} withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) { + // Stub it with our "wsresponse.json" stub file (which is in same bundle as self) + NSString* fixture = OHPathForFile(@"wsresponse.json", self.class); + return [OHHTTPStubsResponse responseWithFileAtPath:fixture + statusCode:200 headers:@{@"Content-Type":@"application/json"}]; +}]; +``` + +
+ +
+In Swift + +This example is using the Swift helpers found in `OHHTTPStubsSwift.swift` provided by the `OHHTTPStubs/Swift` subspec. + +```swift +stub(condition: isHost("mywebservice.com")) { _ in + // Stub it with our "wsresponse.json" stub file (which is in same bundle as self) + let stubPath = OHPathForFile("wsresponse.json", type(of: self)) + return fixture(filePath: stubPath!, headers: ["Content-Type":"application/json"]) +} +``` + +**Note**: if you're using `OHHTTPStubs`'s Swiftier API (`OHHTTPStubsSwift.swift` and the `Swift` subspec), you can also compose the matcher functions like this: `stub(isScheme("http") && isHost("myhost")) { … }` +
+ +## More examples & Help Topics + +* For a lot more examples, see the dedicated "[Usage Examples](https://github.com/AliSoftware/OHHTTPStubs/wiki/Usage-Examples)" wiki page. +* The wiki also contain [some articles that can help you get started](https://github.com/AliSoftware/OHHTTPStubs/wiki) with (and troubleshoot if needed) `OHHTTPStubs`. + +## Recording requests to replay them later + +Instead of writing the content of the stubs you want to use manually, you can use tools like [SWHttpTrafficRecorder](https://github.com/capitalone/SWHttpTrafficRecorder) to record network requests into files. This way you can later use those files as stub responses. +This tool can record all three formats that are supported by `OHHTTPStubs` (the `HTTPMessage` format, the simple response boby/content file, and the `Mocktail` format). + +_(There are also other ways to perform a similar task, including using `curl -is >foo.response` to generate files compatible with the `HTTPMessage` format, or using other network recording libraries similar to `SWHttpTrafficRecorder`)._ + +# Compatibility + +* `OHHTTPStubs` is compatible with **iOS5+**, **OS X 10.7+**, **tvOS**. +* `OHHTTPStubs` also works with `NSURLSession` as well as any network library wrapping them. +* `OHHTTPStubs` is **fully compatible with Swift 3.x, 4.x and Swift 5.0**. + +_[Nullability annotations](https://developer.apple.com/swift/blog/?id=25) have also been added to the ObjC API to allow a cleaner API when used from Swift even if you don't use the dedicated Swift API wrapper provided by `OHHTTPStubsSwift.swift`._ + +# Installing in your projects + +## CocoaPods + +Using [CocoaPods](https://guides.cocoapods.org) is the recommended way. + +* If you **intend to use `OHHTTPStubs` from Objective-C only**, add `pod 'OHHTTPStubs'` to your `Podfile`. +* If you **intend to use `OHHTTPStubs` from Swift**, add `pod 'OHHTTPStubs/Swift'` to your `Podfile` instead. + +```ruby +pod 'OHHTTPStubs/Swift' # includes the Default subspec, with support for NSURLSession & JSON, and the Swiftier API wrappers +``` + +### All available subspecs + +`OHHTTPStubs` is split into subspecs so that when using Cocoapods, you can get only what you need, no more, no less. + +* The default subspec includes `NSURLSession`, `JSON`, and `OHPathHelpers` +* The `Swift` subspec adds the Swiftier API to that default subspec +* `HTTPMessage` and `Mocktail` are opt-in subspecs: list them explicitly if you need them +* `OHPathHelpers` doesn't depend on `Core` and can be used independently of `OHHTTPStubs` altogether + +
+List of all the subspecs & their dependencies + +Here's a list of which subspecs are included for each of the different lines you could use in your `Podfile`: + +| Subspec | Core | NSURLSession | JSON | Swift | OHPathHelpers | HTTPMessage | Mocktail | +| --------------------------------- | :--: | :----------: | :--: | :---: | :-----------: | :---------: | :------: | +| `pod 'OHHTTPStubs'` | ✅ | ✅ | ✅ | | ✅ | | | +| `pod 'OHHTTPStubs/Default'` | ✅ | ✅ | ✅ | | ✅ | | | +| `pod 'OHHTTPStubs/Swift'` | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| `pod 'OHHTTPStubs/Core'` | ✅ | | | | | | | +| `pod 'OHHTTPStubs/NSURLSession'` | ✅ | ✅ | | | | | | +| `pod 'OHHTTPStubs/JSON'` | ✅ | | ✅ | | | | | +| `pod 'OHHTTPStubs/OHPathHelpers'` | | | | | ✅ | | | +| `pod 'OHHTTPStubs/HTTPMessage'` | ✅ | | | | | ✅ | | +| `pod 'OHHTTPStubs/Mocktail'` | ✅ | | | | | | ✅ | + +
+ +## Carthage + +`OHHTTPStubs` is also be compatible with Carthage. Just add it to your `Cartfile`. + +_Note: The `OHHTTPStubs.framework` built with Carthage will include **all** features of `OHHTTPStubs` turned on (in other words, all subspecs of the pod), including `NSURLSession` and `JSON` support, `OHPathHelpers`, `HTTPMessage` and `Mocktail` support, and the Swiftier API._ + +> Be warned that I don't personally use Carthage, so I won't be able to guarantee much help/support for it. + +## Using the right Swift version for your project + +`OHHTTPStubs` supports Swift 3.0 (Xcode 8+), Swift 3.1 (Xcode 8.3+), Swift 3.2 (Xcode 9.0+), Swift 4.0 (Xcode 9.0+), Swift 4.1 (Xcode 9.3+), Swift 4.2 (Xcode 10+) and Swift 5.0 (Xcode 10.2), however we are only testing Swift 4.x (using Xcode 9.1 and 10.1) and Swift 5.x (using Xcode 10.2) in CI. + +Here are some details about the correct setup you need depending on how you integrated `OHHTTPStubs` into your project. + +
+CocoaPods: nothing to do + +If you use CocoaPods version [`1.1.0.beta.1`](https://github.com/CocoaPods/CocoaPods/releases/tag/1.1.0.beta.1) or later, then CocoaPods will compile `OHHTTPStubs` with the right Swift Version matching the one you use for your project automatically. You have nothing to do! 🎉 + +For more info, see [CocoaPods/CocoaPods#5540](https://github.com/CocoaPods/CocoaPods/pull/5540) and [CocoaPods/CocoaPods#5760](https://github.com/CocoaPods/CocoaPods/pull/5760). +
+ +
+Carthage: choose the right version + +The project is set up with `SWIFT_VERSION=5.0` on `master`. + +This means that the framework on `master` will build using: + +* Swift 5.0 on Xcode 10.2 +* Swift 4.2 on Xcode 10.1 +* Swift 4.0 on Xcode 9.1 + +If you want Carthage to build the framework with Swift 3.x you can: + + * either use an older Xcode version + * or use the previous version of `OHHTTPStubs` (6.2.0) — whose `master` branch uses `3.0` + * or fork the repo just to change the `SWIFT_VERSION` build setting to `3.0` + +
+ +# Special Considerations + +## Using OHHTTPStubs in your unit tests + +`OHHTTPStubs` is ideal to write unit tests that normally would perform network requests. But if you use it in your unit tests, don't forget to: + +* remove any stubs you installed after each test — to avoid those stubs to still be installed when executing the next Test Case — by calling `[OHHTTPStubs removeAllStubs]` in your `tearDown` method. [see this wiki page for more info](https://github.com/AliSoftware/OHHTTPStubs/wiki/Remove-stubs-after-each-test) +* be sure to wait until the request has received its response before doing your assertions and letting the test case finish (like for any asynchronous test). [see this wiki page for more info](https://github.com/AliSoftware/OHHTTPStubs/wiki/OHHTTPStubs-and-asynchronous-tests) + +## Automatic loading + +`OHHTTPStubs` is automatically loaded and installed (at the time the library is loaded in memory), both for: + +* requests made using `NSURLConnection` or `[NSURLSession sharedSession]` — [thanks to this code](https://github.com/AliSoftware/OHHTTPStubs/blob/master/OHHTTPStubs/Sources/OHHTTPStubs.m#L107-L113) +* requests made using a `NSURLSession` that was created via `[NSURLSession sessionWithConfiguration:…]` and using either `[NSURLSessionConfiguration defaultSessionConfiguration]` or `[NSURLSessionConfiguration ephemeralSessionConfiguration]` configuration — thanks to [method swizzling](http://nshipster.com/method-swizzling/) done [here in the code](https://github.com/AliSoftware/OHHTTPStubs/blob/master/OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m). + +If you need to disable (and re-enable) `OHHTTPStubs` — globally or per `NSURLSession` — you can use `[OHHTTPStubs setEnabled:]` / `[OHHTTPStubs setEnabled:forSessionConfiguration:]`. + +## Known limitations + +* `OHHTTPStubs` **can't work on background sessions** (sessions created using `[NSURLSessionConfiguration backgroundSessionConfiguration]`) because background sessions don't allow the use of custom `NSURLProtocols` and are handled by the iOS Operating System itself. +* `OHHTTPStubs` don't simulate data upload. The `NSURLProtocolClient` `@protocol` does not provide a way to signal the delegate that data has been **sent** (only that some has been loaded), so any data in the `HTTPBody` or `HTTPBodyStream` of an `NSURLRequest`, or data provided to `-[NSURLSession uploadTaskWithRequest:fromData:];` will be ignored, and more importantly, the `-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:` delegate method will never be called when you stub the request using `OHHTTPStubs`. +* `OHTTPStubs` **has a known issue with redirects** that we believe is an Apple bug. It has been discussed [here](https://github.com/AliSoftware/OHHTTPStubs/issues/230) and [here](https://github.com/AliSoftware/OHHTTPStubs/issues/280). The actual result of this bug is that redirects with a zero second delay may undeterministically end up with a null response. + +_As far as I know, there's nothing we can do about those three limitations. Please let me know if you know a solution that would make that possible anyway._ + + +## Submitting to the App Store + +`OHHTTPStubs` **can be used** on apps submitted **on the App Store**. It does not use any private API and nothing prevents you from shipping it. + +But you generally only use stubs during the development phase and want to remove your stubs when submitting to the App Store. So be careful to only include `OHHTTPStubs` when needed (only in your test targets, or only inside `#if DEBUG` sections, or by using [per-Build-Configuration pods](https://guides.cocoapods.org/syntax/podfile.html#pod)) to avoid forgetting to remove it when the time comes that you release for the App Store and you want your requests to hit the real network! + + + +# License and Credits + +This project and library has been created by Olivier Halligon ([@aligatr](https://twitter.com/aligatr) on Twitter) and is under the MIT License. + +It has been inspired by [this article from InfiniteLoop.dk](https://web-beta.archive.org/web/20161219003951/http://www.infinite-loop.dk/blog/2011/09/using-nsurlprotocol-for-injecting-test-data/). + +I would also like to thank: + +* Sébastien Duperron ([@Liquidsoul](https://github.com/Liquidsoul)) for helping me maintaining this library, triaging and responding to issues and PRs +* Kevin Harwood ([@kcharwood](https://github.com/kcharwood)) for migrating the code to `NSInputStream` +* Jinlian Wang ([@JinlianWang](https://github.com/JinlianWang)) for adding Mocktail support +* and everyone else who contributed to this project on GitHub somehow. + +If you want to support the development of this library, feel free to [Donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TRTU3UEWEHV92 "Donate"). Thanks to all contributors so far! diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Pods.xcodeproj/project.pbxproj b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c3de92b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,9155 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0BD4EFF72DD4194F3E6290A1EAE82CBC /* Build configuration list for PBXAggregateTarget "Firebase" */; + buildPhases = ( + ); + dependencies = ( + FB6BFA54D8E0043795CCFBF57526DAC9 /* PBXTargetDependency */, + B246D60A4784E7242E6F9573F6581752 /* PBXTargetDependency */, + 0C26C138EB21155893EB3AAE8342452D /* PBXTargetDependency */, + ); + name = Firebase; + }; + 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 14608CC6B8CF27B7AF9B3D5F5B6F8607 /* Build configuration list for PBXAggregateTarget "SwiftGen" */; + buildPhases = ( + ); + dependencies = ( + ); + name = SwiftGen; + }; + 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B345AD1AAB27ADDC33CD59391F2A2578 /* Build configuration list for PBXAggregateTarget "Sourcery" */; + buildPhases = ( + ); + dependencies = ( + ); + name = Sourcery; + }; + 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0A1FEBE926726C9A3E064BDC1F0E7D33 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + ); + dependencies = ( + ); + name = SwiftLint; + }; + A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */ = { + isa = PBXAggregateTarget; + buildConfigurationList = EF7E77D70CE9CA6FA1C9D136EC7A4F62 /* Build configuration list for PBXAggregateTarget "AppCenter" */; + buildPhases = ( + ); + dependencies = ( + BC9C5B4317B57C84FDC286747A6C68CD /* PBXTargetDependency */, + ); + name = AppCenter; + }; + ABB048B191245233986A7CD75FE412A5 /* Fabric */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 44BF99169533508633331B4E79AD527F /* Build configuration list for PBXAggregateTarget "Fabric" */; + buildPhases = ( + ); + dependencies = ( + ); + name = Fabric; + }; + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 615A1A40348710AE156325FFE219FE30 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */; + buildPhases = ( + ); + dependencies = ( + CCB4B2FB4874EF61E26C0C42BF0A95E6 /* PBXTargetDependency */, + 73A206221EDC7792C0724E183F29C491 /* PBXTargetDependency */, + ); + name = GoogleAppMeasurement; + }; + B593490A33943610DC035C394E10D07A /* Instabug */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B7E7737163084DF0736A1DA737474EA7 /* Build configuration list for PBXAggregateTarget "Instabug" */; + buildPhases = ( + ); + dependencies = ( + ); + name = Instabug; + }; + C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A2C2BA6807BBA455470E664F6B40CF02 /* Build configuration list for PBXAggregateTarget "Crashlytics" */; + buildPhases = ( + ); + dependencies = ( + C9EE7669C499C214D32673DA70F448B1 /* PBXTargetDependency */, + ); + name = Crashlytics; + }; + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 991E43F74ED979CF133D44C61CD0896E /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */; + buildPhases = ( + ); + dependencies = ( + 3792EB87049BCC72EB8B88E35FC33ADB /* PBXTargetDependency */, + DC9B574DFA929B605978935F3BDB7CD8 /* PBXTargetDependency */, + B59975B1711C1B93F51408259602A32F /* PBXTargetDependency */, + B5290BC5AF5A74B7D2919728FDE4472E /* PBXTargetDependency */, + E1D1984FE10DD52FB5F2B2F12B34CD23 /* PBXTargetDependency */, + ); + name = FirebaseAnalytics; + }; + D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 590CEAC43BDDFAA9598150F9D23A62A1 /* Build configuration list for PBXAggregateTarget "FirebaseAnalyticsInterop" */; + buildPhases = ( + ); + dependencies = ( + ); + name = FirebaseAnalyticsInterop; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 002B61DB441C6864402B2620001F2D24 /* Special.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E603AE6FAEA107641D9E8499AD28ACD /* Special.swift */; }; + 00615AAC8F76F88D5B261CDBAFFC42CC /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E893CE5D8A792CBF4C835E33C903AB37 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 00B3DFC8711DBA5BEFD89F179EFD44C1 /* AcknowledgementsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91A527A11C0F5C0E19DEF21E7B9C7F7E /* AcknowledgementsListViewController.swift */; }; + 0100B51AAD85D2A5B7C3725618933398 /* UIView+Lookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52569BDA16818151E3735016A95C16B /* UIView+Lookup.swift */; }; + 021DB76932CE50DD90304FEBFCA8BE77 /* FIRMMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = FDC9DBDC4B19FB33CDC14DE23114B21C /* FIRMMessageCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 028B2CECCB9AEA8424D7C00138A38431 /* NavTitleTransitionBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01502087710687B101E4DBC35B149B69 /* NavTitleTransitionBehavior.swift */; }; + 02FBDFBD52654C16E8616F45114FAA14 /* TailoredSwiftTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F7DFC7F79DE29AD380D6C23EF374F66 /* TailoredSwiftTextView.swift */; }; + 03EF25966CA31FFBC31B8044BBDB7C78 /* FIRMessagingCheckinService.h in Headers */ = {isa = PBXBuildFile; fileRef = 7930F6E4B1DBA1F8B3A51893DC47D6D9 /* FIRMessagingCheckinService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 040519868B2FE15E71CE862276B5FB0D /* Anchorage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 569222352AED8AA275E1295F319C179D /* Anchorage-dummy.m */; }; + 04EF7CA88D2E1D49B56D74409399559A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 059037195C74C676763DE7253C64DCAC /* FIRMessaging_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E5AF5D638A5E46AC1F536B0D9FC686E /* FIRMessaging_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 05A179D28D1AEFB2994F50DF04732ECC /* GULAppDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F492B106E8EB1E2C72059F4CEC2ADF4 /* GULAppDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 05EBDF811901C96CB4A388C239C95E5C /* pb.h in Headers */ = {isa = PBXBuildFile; fileRef = C146F3AD61FC35B7C5ACADB293B2E5CF /* pb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 06B290D6C5B112EC54DE4AAF0921A969 /* Compatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C88D2EB51952A1D85A0AB4AD8FE1D6 /* Compatibility.swift */; }; + 07004386F300F8DD87A2D100C010521B /* FIRInstanceIDCheckinStore.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6910A0DE802228534590DFC11D90C2 /* FIRInstanceIDCheckinStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 09BBB2DFD0CCA4F842ED217E1ADE6141 /* nanopb-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 22D8C3460BFD762A935246A9445DDDB6 /* nanopb-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 09F7DF5894417D5165C5B1873E46B448 /* FIROptions.h in Headers */ = {isa = PBXBuildFile; fileRef = D2B4AA2B21255F7A6AA09F0E059321BF /* FIROptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0AAA11C4CFB301157A24BF56A7C1ED7E /* GPBBootstrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 670326828280195E95A7805733428555 /* GPBBootstrap.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B9AC443AC8498AB675F72F8A84D961D /* CoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = A39DC1AB08D7C48D33B0213FC070EE91 /* CoreDataStack.swift */; }; + 0C0BF1B04934ADA346E62844B9324E2A /* GULOriginalIMPConvenienceMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 6407CC37ECE767179AE4ED00301D5C52 /* GULOriginalIMPConvenienceMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C9D3548AB6302BFF4E52AB249E9B2FA /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C395986E3E5F5139E1E2D48B13C6B14A /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0D110E5F8DB3A38046128C3AD51467AC /* FIRMessagingSecureSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 37E010E6C2F14B116AD0A6E40D547F39 /* FIRMessagingSecureSocket.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0D9138EF60798B8D013C354FFC3F956C /* GULLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 319AFABD7CD5670EEEE2D2BA15A360BD /* GULLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0E47DE1D5D4C7AA8034D1B7F63774BF0 /* FIRInstanceIDTokenDeleteOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = B94ED403343770A491208CD276342FF7 /* FIRInstanceIDTokenDeleteOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0F8CD4F146F1C58231026AAF09FAC5EE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 0FD7700F7E5A81A21AEB14558CCCD67B /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FC123B26387B1A38B1AAB531554C64E /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1011297752537301D863BE2D4B01E43A /* OHHTTPStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = DB5BD78F6D7A28ACB840F946DCBA826F /* OHHTTPStubs.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 10239177A8AE0CD597F3FDCCDAC21FFE /* fr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 829D6EBA77079A9CFF95E76253E1B175 /* fr.lproj */; }; + 1077DE8C92C90C40F4D8ECE47B48EDB8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 111E7E93B775DC49472ABF1CDC8BD6C7 /* FIRBundleUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 367F00084F5782810F06E3AE60988239 /* FIRBundleUtil.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1168EAF844C5167A969F992B39124E95 /* FIRInstanceIDUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = A3AA81B96ABF2101A80128229B5253C0 /* FIRInstanceIDUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 12C27A0E31DE9B1B0B5E54C2C429BD54 /* GPBWellKnownTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 258251CAB54F309E8E640653850C4B32 /* GPBWellKnownTypes.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 130BCF85E0BDD69B046F3000354BA0B1 /* FIRInstanceIDCheckinService.h in Headers */ = {isa = PBXBuildFile; fileRef = 5215C876BC30D194764B41B21031B21F /* FIRInstanceIDCheckinService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 133BA9EE26B755C23B694417B33A6936 /* FormattedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F85F03D3204EDFA79866F18C991616C /* FormattedTextField.swift */; }; + 13818F8210CF5628758D110549396C75 /* NSLayoutAnchor+MultiplierConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2F76C4975A9F75ECFED7459246BDCE /* NSLayoutAnchor+MultiplierConstraints.swift */; }; + 148F3B7A2FF4E9CAC78C9E5AB0286CBB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCE4EFC833EB090ACE8EAA95D8F1FB5D /* SystemConfiguration.framework */; }; + 1735E3217A03B5B4EEFF084033ABE1DD /* FIRMessagingRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = E3AE805A7D220717142177291A6563DD /* FIRMessagingRegistrar.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 17CA76C0BACF692C96BD0A789D76C08D /* FIRMessagingPubSub.h in Headers */ = {isa = PBXBuildFile; fileRef = 7798FFAA50C6E5C495F258D8A51AFCF9 /* FIRMessagingPubSub.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 18104AFA575A3CFB614915516FA8A1EF /* GULSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = A668229ECF671E377647F4DE649FE2D9 /* GULSwizzler.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1931E725A11B3C13986AB78A8130111C /* NSError+FIRMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E51F53C43C26EC84AD204A2DF58797C /* NSError+FIRMessaging.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1A0898925095DFC70512C1A28BD9F587 /* Type.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 05E39D129D919E418F8D526AC9591021 /* Type.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1A57D555A841083C708009478DC31FB5 /* GULNetworkURLSession.m in Sources */ = {isa = PBXBuildFile; fileRef = F6B71CAF2E55E96D2C79702EA17AC62E /* GULNetworkURLSession.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B586862269C42A863000C3B70991A0B /* GULNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = E73E251E3CF96E1495BE3EC085526D94 /* GULNSData+zlib.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B5BAD2AE0BDB78D1797A3F079F2DB27 /* FIRErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = AC024504A5C4B47AE13B434EA483D427 /* FIRErrors.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B8BC5D48142213B30D7DB0D0B067738 /* FIRMessagingContextManagerService.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C651771BDA251122C0517F98DD229C4 /* FIRMessagingContextManagerService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1B9376E58DD7B9226E8EBA79391DF110 /* GPBRootObject_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EE85328C2AA2BE65AC5476B9A3A4B9A /* GPBRootObject_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1BCC66B692E9EDE5C903B4469B4BCE57 /* SDStatusBarOverriderPost11_0.h in Headers */ = {isa = PBXBuildFile; fileRef = ECE318A98BEDBC9D92401EFDAE6EAC84 /* SDStatusBarOverriderPost11_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1BE02480F93F6FEF703BC98F779A8FBE /* GPBCodedOutputStream_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1064EA2176F4289B3F2DC02849A83825 /* GPBCodedOutputStream_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1C202B0C77A04F7D0E65F399808DBB11 /* FIRComponentContainerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E4A10F6099BBA9290EDF1F50E4E1E06 /* FIRComponentContainerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1C3586AF524004892635EFD9A2F411EC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */; }; + 1CD0155BAAB0AF2CAB66FF0A801DD974 /* AccessibilityHeadingLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9B9847934B602C43CAC9AE7E2EBD36 /* AccessibilityHeadingLevel.swift */; }; + 1E460A03738161788BA4D0258D3C2657 /* AdaptableTextContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF9BA9F1FCE9E687C9236562D28FBBF6 /* AdaptableTextContainer.swift */; }; + 1E84D4A521B67526F319DBFFCE9486B7 /* GPBUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C5A26153063FDC9CF29CACEBFDCE19B /* GPBUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F680A61812FACE2D5115195328CA3DF /* NSError+FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EB8515E357A8EA23661EBCD579561C3 /* NSError+FIRInstanceID.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1FA20690DF9A5043204742E88A203343 /* StringStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 786594362231C88055784CE1F30F160D /* StringStyle.swift */; }; + 203BE416FA99DFA5A8A48CBFD3D12D1D /* FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = C513955DA0F2FA1EC966C5DCB86267DE /* FIRInstanceID.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 220FF13741674D3D3CF5BAD8DFCE5E92 /* FIRMessagingPendingTopicsList.h in Headers */ = {isa = PBXBuildFile; fileRef = 662B607559C369907018526CD34E7A82 /* FIRMessagingPendingTopicsList.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 23A2410F3C4DE63B77014C9DE596F51C /* FIRMessagingTopicsCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 623AE596A3622CB246F0C91BF962A5EA /* FIRMessagingTopicsCommon.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 23B15157951EFE8223491E517FB38492 /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 78082F41A23883083EE4061BFC18A4D3 /* FIRErrors.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2612E406DE2FDD81958D99713579DFE4 /* FIRComponentContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CF43C772DF570A45DC9831438386FF8 /* FIRComponentContainer.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2646BB4FDA2D1690D9DA61405740F25C /* FirebaseMessaging-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F16A3F715737A448BD6736FC7CE8C23 /* FirebaseMessaging-dummy.m */; }; + 26939CAD52ABAD1A55806F176550DA26 /* FIRInstanceIDKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = DB6E2DA2A7458E3619DF8D70A1EE9011 /* FIRInstanceIDKeychain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 27168CA32C4871EEE4C1CE2D5909485F /* MutableCopying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 793A451BCFED3B0D33EF91ABA0E76DC0 /* MutableCopying.swift */; }; + 2723FECBFB4E4EE1EC645516FBB232D4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 27A8DB4EE609E1FABE7EA7835B6FF28B /* FIRMessagingInternalUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 29977CBD0F0F1352A376A22E58D14F56 /* FIRMessagingInternalUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 28292C6F27C2567FFD9A0C3130CFC626 /* ViewControllerLifecycleBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D70F6C27F2262A020CDFA6DBA6E0A95 /* ViewControllerLifecycleBehavior.swift */; }; + 28501C3F19644C8E8888E168B5163A2B /* FIRInstanceIDAuthService.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B76802A61020D8F2FF87DBC22F95501 /* FIRInstanceIDAuthService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 29D8A0E1833835AE95BB8D68783E01D3 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C494458D65556B106276B45877C5407 /* FIRLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 29F77423AD4D91EA6AA353C23B5C80FA /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = B53967F27884E26D24DE4B390642290C /* Duration.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2A06EC8F16F9A176A6E8969AEFCF557E /* FIRConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = B5391DB5CF7FE004619D4F1920521EA2 /* FIRConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2A81ADD3C0C26EEFD1409AD35142E0AF /* Pods-Services-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 43F95FB28B3B3DDC58B3E70C591BD759 /* Pods-Services-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2AA0A2B7267E8E75525D003D9A96E6ED /* FIRMessagingRmq2PersistentStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 846244C0EC47A8A7BE9B1E2506F77C50 /* FIRMessagingRmq2PersistentStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B088D091DA7DA702E17C2022DFE2D14 /* FIRInstanceIDTokenInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AC714289EA97E67199CA997655EAF27 /* FIRInstanceIDTokenInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B6BD33D9BA13D63533BF7A016186C63 /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B9F61513C3569FB8F5F80587BD0802 /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2BC2424190D3B6288B51C3DAAC70FE0D /* FIRMessagingCodedInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = FB1B0B49E7137AD9BBD29842C2A3A7BD /* FIRMessagingCodedInputStream.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2BD4A62FFC2595A77CF36ECD209FAC2C /* UIKit+AdaptableTextContainerSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D4DE2FA59344D4592D75A8D5A4137CE /* UIKit+AdaptableTextContainerSupport.swift */; }; + 2BF26FA6F5CA189C337AD83F534BC3D7 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0613D7FC4E5B1B63B0C08F9883F7B6CB /* Timeline.swift */; }; + 2D409981B90BFACE059F7069003F5372 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D7EE49F14DA03DC27AA4631DE48483 /* Result.swift */; }; + 2DF1DEC33EB066E5581440CD6998386C /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 72AA8EF20A9E0ED207B17A82A67948D7 /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2E5638B808692AE3B2213A66E618B793 /* GULNetworkConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 9221AE50CB51C7E8CD93A956CC3EA7C2 /* GULNetworkConstants.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2EF7C4DD8AE3B593B8DF4E2935543F45 /* NSAttributedString+BonMot.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA27AEAA510EE20594C0FCF896C53040 /* NSAttributedString+BonMot.swift */; }; + 2FE5FAA4B2358E5E17D36BDB048F9160 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1248BFF6EDD2B0B1963D8E18335E0DCD /* SessionDelegate.swift */; }; + 307995802DBDCAE24CD40AA467DFDD9D /* Swiftilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 88F89AA47577A480D576C38E3EDFADAA /* Swiftilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 31F595EB1AE5D570993770123D9A2A5B /* Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7558233F38BB01572FA6F6C87087DE05 /* Keyboard.swift */; }; + 3200DB013281B43E28A5C67E98EDCF1B /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = ADB4B0347B4897392B2245F4E44D0AC1 /* GPBArray.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 322D81E9DF88D46A7F0B60EF4B7CB1CA /* SDStatusBarOverriderPost11_0.m in Sources */ = {isa = PBXBuildFile; fileRef = AD72DEE352EC54E08A0DDA10EEDB3D49 /* SDStatusBarOverriderPost11_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 33108ECB357D1206B36ED2F85AC12269 /* GPBWellKnownTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 20D53BC1D9D046786E39FFC97B7B43A7 /* GPBWellKnownTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3322584F7CF6DD027B79F6BCA4651CA1 /* FIRComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 900494C92D1BC8DD44B41A1E185446A2 /* FIRComponent.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 337AF23300B055F9D0AF0BB5AC2F55E9 /* UIStackView+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5A2D89B160FEBC3EA6D9A26612606E7 /* UIStackView+Helpers.swift */; }; + 33C1DC1D1DBDCCD13C278B789AC82B0F /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A572C6721447ABE0F589A4004BA6EFA /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-dummy.m */; }; + 34F9A43BEE167441599A1035E0C14F96 /* Anchorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13FC2F155F0438B5C95978061F39743F /* Anchorage.swift */; }; + 35E679A58A9EF087D8AAFB484914B64E /* GPBUnknownFieldSet.h in Headers */ = {isa = PBXBuildFile; fileRef = B7B04D349B7F6EF4AB5D84952D2A53DE /* GPBUnknownFieldSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 360522FAF4C83FF5BB33C984F4D293B5 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 994790A4BDFB35C5FEEEB4B16ACD0073 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 365196A7B4EE1C83C432D345AA839C88 /* GPBDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = F33A6CC0B7DD266D5F442790D44ACD25 /* GPBDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3684FB4C4B318425C246914FE763A0CC /* TaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 548F85D6FB2D9B296B3CB2FD0B313CDC /* TaskDelegate.swift */; }; + 36D435F6F2D69F1A933BAE5D27B0EF85 /* GPBUnknownField_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DF285A229D15CB8F3DFBB3DD3DC7884 /* GPBUnknownField_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3864DBFDFD3CA45C50C5E35FED55D1C6 /* Protobuf-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D7500D2B23B7DC69CCA7B61577BEAD0D /* Protobuf-dummy.m */; }; + 39074F282BFA3893780C3F2330271BFA /* FIRInstanceIDCombinedHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 26880FF9FEB2270469CDC3F44CFC51BE /* FIRInstanceIDCombinedHandler.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3957709DBEF6C37401EF8F32B962985D /* AdaptiveStyleTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F95AA7ACDE907999406636AE9140BF79 /* AdaptiveStyleTransformation.swift */; }; + 398916FB2E858FCF90B787DF390F0646 /* FIRVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = D436B935FFA96DDB042376CB5C11E29E /* FIRVersion.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 39CE61B6B67AAA879293052A016A9B44 /* FIRMessagingVersionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C1809F979F3942E4C48A86D0F20B10B /* FIRMessagingVersionUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A1C7551BF0986016F6C2537B5E2733F /* FIRMessagingRmq2PersistentStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F13E67C41FD3508A00AC0A6F6CA8A43 /* FIRMessagingRmq2PersistentStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A6073E24514DD7FC8539E5C9BD6FF3F /* GULReachabilityChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E98DDB0684CD0EED258207851A2A13 /* GULReachabilityChecker.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A68C5510ECCCB664B640F57F86435D9 /* FIROptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 97EFF3947D869F0FC7D7D08A1B3B0A6E /* FIROptions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3AE9A26503715569C678C2C331591663 /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FE7B5BE33FDB3387A107014CDD4C22 /* Platform.swift */; }; + 3B17099ADDBF828A11994064917317EC /* SDStatusBarOverrider.h in Headers */ = {isa = PBXBuildFile; fileRef = ED9E474AFCCD58C67C788DC90A8A9AD0 /* SDStatusBarOverrider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3B8C1EA2A930ED9F1F28457FF7860F06 /* AcknowledgementsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D6419DC93CAC1E865DD9A730B5C8623 /* AcknowledgementsListViewModel.swift */; }; + 3D65EF2ED72527D8BD4359402DC8DE54 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD7A8A7135C2FC81974892005E66656 /* Response.swift */; }; + 3DA83DFE11641ABBF54EED0F6D91658C /* FIRInstanceIDKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = DB1194551671BF12886B8DECFEC28149 /* FIRInstanceIDKeychain.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3EA25AB8FC4048123BF2D50D8AEBEFA7 /* UITableView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 552F3B93D76BA12F543F0275D11FB3F6 /* UITableView+Extensions.swift */; }; + 3F318A17631E107812E804B75FFB7FA6 /* GPBProtocolBuffers_RuntimeSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FF4D0CB4786B5D9882E4D069869A3CF /* GPBProtocolBuffers_RuntimeSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 409D2E6AB1246D3B41550EC6F8B68695 /* FIRInstanceIDCombinedHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B49BB3E350F98DF8781264F7BB9D61B /* FIRInstanceIDCombinedHandler.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 40CAB5AAB5CF579001117DA2892ABA3B /* FIRInstanceIDTokenOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 08DA9B3BA661AA7124AE37AFA1396048 /* FIRInstanceIDTokenOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4137F7B8D747E67F776B744E4FF5A116 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED0360339FFD929C312164430AECEF5 /* Protocols.swift */; }; + 414165239CE300A52CEB93BE48E70607 /* GULLoggerCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D8C01D7DC37A7E86CB6EB912842D669 /* GULLoggerCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 41D8B6DE590FB9C57F9878F4A384C223 /* LifecycleBehaviorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D1F592A03F29834A482A527C26C43F1 /* LifecycleBehaviorViewController.swift */; }; + 42BC5786C34E1EB3171356AF8E67E607 /* Tab+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9457CFFC68284D195CF10F91CD0AB794 /* Tab+Adaptive.swift */; }; + 42D8642270868B9E53CD23BE32323A0C /* Tracking+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7852EA1E7C25798259AEA5BCE126639F /* Tracking+Adaptive.swift */; }; + 44B74653D503CB502B265C0366ABF103 /* it.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B7AD2BE9A6C9E2298E7917BF8FD6E425 /* it.lproj */; }; + 44FB46D5982B3E156F7AA4BEE081B463 /* FIRInstanceIDAPNSInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 88B5959D5B7A3E36DDEF6EA561F00502 /* FIRInstanceIDAPNSInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 45E7C2C769D51937061338A69BEE2316 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 46132B8EB028FC0BD59C6B8293151984 /* FIRMessagingPacketQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BA9EA5998AA76F74EE798C3CBBECA9D /* FIRMessagingPacketQueue.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 488F9DFC7A23F9EA87DA50076865695A /* GPBCodedInputStream_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = D7E5680FC53E7E9F3D5CDFD636890134 /* GPBCodedInputStream_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 48DD3117F88694C0FD530B7D951E585F /* UIImage+Tinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8E677CF6BD8B668E00639F75526D6FE /* UIImage+Tinting.swift */; }; + 49346BA8A9F65D4EB67A452D73543353 /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F4647B8C0D1352B1C58A2CCAC8F8A1 /* ServerTrustPolicy.swift */; }; + 49831F5B3224292A50B5E474627F4066 /* FIRAnalyticsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBA28A120B7A31F4D7E17E23F881916 /* FIRAnalyticsConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49894777E431600670C3413CFD08CBAC /* FIRInstanceIDKeyPairUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F4539DEEA1DD2E3E786DAB20A235E0B9 /* FIRInstanceIDKeyPairUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4996917AB6F783603F868111BEA8E18B /* OHHTTPStubsResponse+JSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 73047CD3A9D6F102084B6565479FD975 /* OHHTTPStubsResponse+JSON.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49A539B6B325126F22AC170396E5B6EC /* SDStatusBarOverriderPost8_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 180977BDD0E3E3ED4CC91DF5BCD29868 /* SDStatusBarOverriderPost8_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49B7354094136C862C02D3564F82F95C /* Emphasis.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45D8D0A1979A555EFB7FFB40FE9E3B3 /* Emphasis.swift */; }; + 49D4D750DDF02487C8AA4B26B1D85942 /* FIRInstanceIDKeyPair.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C37EAC158A77C4D6904556D7810ED89 /* FIRInstanceIDKeyPair.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 49FF7B5676B99AC5BC66CD274572D5F8 /* OHPathHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = F582E21899CB1B7DD3C29A9B5AB73287 /* OHPathHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BAB4E1DF3D4D6AF88A8508E3A2F09A8 /* FieldMask.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B333D83F4602F037A199CE1061A7A79 /* FieldMask.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C1E5B258AF3CD751A7D6DC2F9EFDB64 /* StringStyle+Part.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2CFBCCEE9CCE0907B805548198E2D4 /* StringStyle+Part.swift */; }; + 4C4E5BAB5F6CEF8DC0184E7045DE6319 /* FIRConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 106E91C219A27E966E2F6168D1D7F3CA /* FIRConfigurationInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C650C838B9A46B8869FAC4ED9167B3B /* SDStatusBarOverriderPost9_0.m in Sources */ = {isa = PBXBuildFile; fileRef = 047E636E2BACE2765A28ADD8F0A0E5CA /* SDStatusBarOverriderPost9_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4D4DD4E2E2F97F489820569260C7BBEF /* GULNetworkConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E381DBDE829EC743F4F0A730A0EA4E5 /* GULNetworkConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4DE36299CE267FCDD391EABEA81FFD85 /* SessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0CD839E48FC413F0F119BC2DF2B9FF2 /* SessionManager.swift */; }; + 4FC8500AC1BDC6610782C5C287EAFB46 /* SDStatusBarOverriderPost9_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 13EF5B0944ABC90005395BF63E59D1B9 /* SDStatusBarOverriderPost9_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5066B89BFDEBC3087F0077E0E19D605A /* FIRMessagingConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0951EED81BCFA0803E2B141DE332E11D /* FIRMessagingConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 50A0609DC011B95A498F342D6A496297 /* GPBDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 168D0C5421335ACFB5EBB53C584D8B5D /* GPBDescriptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 50B4399E699415F041C1E8E4DB7A1D07 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = F2181E7978D4D5EB57672242678285CA /* OHHTTPStubs+NSURLSessionConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 513E4B1817532226E5F18D5BC9616970 /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D5ABA89BFABB034F15503FA4EA2C665 /* Struct.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 515B9D3F0278919FFC0BA69A4A50BF3E /* AccessibilityHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 075A60A7C92F557056B739FD7E6BD32C /* AccessibilityHelpers.swift */; }; + 51E49408AF7F12CE0559236B11C26465 /* FIRApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 137550D164A3DC3110CE137D5BC383BE /* FIRApp.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 53DC83DDE0F07B1E642EDD0A2FDFCC1B /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E200831632A5DA6FE18A80ED063AA8 /* GPBMessage.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 55F7228A18EA4ADE7388939284DC1828 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4AA562F866C56D8D686538218F79EA /* FIRLibrary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 56284F2A2FBC7E52A29EA14CA7DC047A /* zh-Hans.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9217346EC5CA9E35B7D5CC7A1AC82A9B /* zh-Hans.lproj */; }; + 5709B0AB8B9B6E3FD552E4D0E72A40E5 /* FIRInstanceIDAuthService.m in Sources */ = {isa = PBXBuildFile; fileRef = 781146DAC6F2B33CBAB88F5B7480DA3C /* FIRInstanceIDAuthService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5762BA089A3300D0CC1348BB1C6BF5D0 /* FIRInstanceIDStringEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = EC198B2667B7ACBED262624C674F40C0 /* FIRInstanceIDStringEncoding.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 58052E699714C0A50B87E6259F53F415 /* PlaceholderTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59995D0C9E351E7C567DF118C940304B /* PlaceholderTextView.swift */; }; + 588888EDDEAB87B7AE65F4417BB0895E /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = E458A4DC6C3E79475F17EE8A2379E327 /* pb_common.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 59797280DBA2DF4FDD7E2FB08A37D99B /* GULUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 36624989E8CA8F0B22557AD8E3ACAEEF /* GULUserDefaults.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 59DB4ECFCA9DC741DFF14E4456709E22 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26820BF7BDA3D0A1D104CE81E2CF5EEE /* Notifications.swift */; }; + 5A08019AA5486E6DCA36E4EBD3C52A1F /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0EDF0E175A8ABAE1DC6C2A8C67270 /* Validation.swift */; }; + 5B7FBA1711906689F88D73F89241C604 /* Ligatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4EB1163B98FFAB7C42AB21C3ACF776 /* Ligatures.swift */; }; + 5D01F5103E9821505EF578009E14403E /* FirebaseInstanceID-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FD395C6B080D05AA0E9B521C84DE95C /* FirebaseInstanceID-dummy.m */; }; + 5D6901CB7E479AF1C5F8A340BABB727A /* GPBRuntimeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D50A2051D90DCC03E026A0A56A46F1E0 /* GPBRuntimeTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F12EFB41C6F7259375BF3E842CE980A /* SourceContext.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD0138F17C5CEC5217CDE58354221B3 /* SourceContext.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 61C1F86EDCE280896041FC1FC3DD8187 /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11A4E7961F768D0892E18D1649C5FE4 /* NetworkReachabilityManager.swift */; }; + 623966AD950C81665095F64F9D4201CB /* Pods-Services-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AF4C07CB531C2A20C075F1E2F27F9807 /* Pods-Services-dummy.m */; }; + 6239F27D209AFEA6F20DC38D2EA8BF53 /* NSURLRequest+HTTPBodyTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = 92B3A83AF7CBD24CFB27352A8A473464 /* NSURLRequest+HTTPBodyTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 625AC25C0B02E9914E2F7B57ECEDB850 /* Alamofire-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 01CDC0351ED7CEC107FB8A77489F99CE /* Alamofire-dummy.m */; }; + 629542A04865B500B62B43F92C8865D1 /* SimulatorStatusMagic-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EBEFE4F4DF5F7C86F8F3F2C30FC2380 /* SimulatorStatusMagic-dummy.m */; }; + 63E56D00C55C0A10C4B75F082AF81B6E /* GULMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = D8D631A479FBF2CC1551FFD90D0D6CCF /* GULMutableDictionary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 63EACF4772E7F89957A22DD4E216C3F6 /* FIRMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = E774767ADA7D8B661ACBB80E499003DD /* FIRMessaging.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 643932FF6C60A7B50E69281BEC283DCC /* GPBMessage_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 01FC0E2DFCCF55217572DC39EA5C6163 /* GPBMessage_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 64608DAE6E2BA2943D7382FC8434201E /* CubicBezier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE2591C629B8D1D99F7EB621AFE24BA /* CubicBezier.swift */; }; + 660EE0BDDC1B6E8665904E38D90D31C6 /* FIRInstanceID+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 18DE3A66023F031C118C9FA1671ACC93 /* FIRInstanceID+Private.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 66E368242E78C0FD771A32B6FE1931A8 /* FIRInstanceIDURLQueryItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 45BCED46E7DDF7FBA46DB0CC8B1E58EB /* FIRInstanceIDURLQueryItem.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 66EF408EFC3D695477CAAA86191FF5A2 /* SimulatorStatusMagic-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 422661E817D097522D8B376CDBD2FD9C /* SimulatorStatusMagic-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 66F6BC937ACA5E47AF09DB8ABB6D7645 /* FIRMessagingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C51C1D95A23094AED0ABE47DE23F077 /* FIRMessagingClient.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 672DC3874BA0AB02B90F8C35DE880034 /* Image+Tinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44A4945BC33C7C54BB4A7520594B486 /* Image+Tinting.swift */; }; + 67D67C17FCCB5F83FF620BD048630184 /* pb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 63782DD22D80D12F0478617EBF8A6E9E /* pb_common.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 67DE466AD41481FEF9115827C53B66FC /* StyleableUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E6EBF71B53225C8F92782A7CC19944 /* StyleableUIElement.swift */; }; + 68333497E7CEB0B383B8F14BF0B0B6BE /* GPBArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A12FC33DD08260C9C378A9C2A227833 /* GPBArray.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F48879AF4FFB5542723DDF132E7BBF /* FIRInstanceIDAuthKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = D5DE97AD0E8D2A97E134344E7227B548 /* FIRInstanceIDAuthKeyChain.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 69AB47B1E87B21D5AB731A8B4F8A5C6E /* FIRVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 772EBD4355380FAEEEE486F50277CA1F /* FIRVersion.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6A54BA358BA6EA4B21A472B16B0F2136 /* FIRMessagingPendingTopicsList.m in Sources */ = {isa = PBXBuildFile; fileRef = B67FA446F6A78388566D90BDD02B2175 /* FIRMessagingPendingTopicsList.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6A5EF7BFD9E1F744141F8FADA93CC40C /* FIRInstanceIDConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 11EF24F4E2A79E63296F2034D972DD0A /* FIRInstanceIDConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6A9ACBEB61712282B87B0A3090045B36 /* FirebaseInstanceID-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A86060F6B97532F283FE392A2B356F3F /* FirebaseInstanceID-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6AA8F0D7888C5B32C0D72865D646F69B /* FIRMessagingDataMessageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FB7E0D532911BBB43E2A8AF72818A0DD /* FIRMessagingDataMessageManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6AC487E61CBA42325EAEE431BBCCA6C0 /* FIRMessagingContextManagerService.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B4A56D8EB5978D426BDC59DC1AA5E2C /* FIRMessagingContextManagerService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6B02408E859D41775E7C99C72211E233 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 6B9902DEB83C255B7F7BE5B97D95CB8C /* FIRMessagingConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 67E6336A4DE03D2B54BB4E2D5C377405 /* FIRMessagingConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6C12C62F4EB60D4AD5F161942A4D7A1F /* UIViewController+Deselection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEB3012499F8855E88664D9000D9DCE4 /* UIViewController+Deselection.swift */; }; + 6C47FCB1BC1088F8D9ECA92E2D2C0EE1 /* OHHTTPStubsResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9D78BDFE3971F2EF43F1EE93290481 /* OHHTTPStubsResponse.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6C654A56978C6D1886240834580D72C3 /* Alamofire-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 55D73A9343E88A26AE65A4223D8C07DF /* Alamofire-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6D80417305501039BA0BDDB62948E193 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 6E8015F43C774A2A6B848A4850A5A01B /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F446B65463479D1A1BC7E615FB1DB21 /* AboutView.swift */; }; + 6F08BA4C77195B13666BF9D048734345 /* NSURLRequest+HTTPBodyTesting.m in Sources */ = {isa = PBXBuildFile; fileRef = FB31D468DB67CC3C68E932FF60724283 /* NSURLRequest+HTTPBodyTesting.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6F7B7BD79C3CFF57A0AA78D63E5E3875 /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D3820BB2870B22224C025F97B495A /* GPBDescriptor.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6F7BC8C09DBD46C7EAB60340AA5AD1A4 /* ru.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F6EDB24AD1F08BD38D4E0B70CC036804 /* ru.lproj */; }; + 6FA68690945C1A9D56524BE6EEB1B23F /* GULNSData+zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = 966E61D7CDD4B8F269B4C52F6C9D4E6F /* GULNSData+zlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 70A61B041ADCE42401597F1F1E36A137 /* FIRMessagingReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7750A59221DB77FAF80CF7B06B985ABA /* FIRMessagingReceiver.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 71775A89A3802A1BA58BF1BB41DDD9A1 /* FIRMessagingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = ED75C449FDA4BD587531DFEE93D42918 /* FIRMessagingUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 722C5094761B72D30EB0CCB1CBD1BB5A /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = D7EC6B48A447510995672266B84A0112 /* Empty.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 72E64E250ECE3FED90F8E229980CD42F /* FirebaseCore-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F3787E17CA4EF4DC7B09E88A20DD9847 /* FirebaseCore-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 730B332BFCCE80D74F954AB5D5018B07 /* FIRInstanceIDBackupExcludedPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 466630EDA0868AA0AB1CEBACE48F76AB /* FIRInstanceIDBackupExcludedPlist.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 73C84761F0777ED77BDA9657F0D88C33 /* FloatingPoint+Scale.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1364213BD031AD3BAD42D9E69571ADD /* FloatingPoint+Scale.swift */; }; + 748616D83CFB8AD5D5FC47C2EDB8FF36 /* GULAppDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DF740D3ACE024C9F6487F0DBFBBC4B7 /* GULAppDelegateSwizzler.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 74CFDB81D12600FF74EAF4FE27423E07 /* Protobuf-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A2450A9AC3AEDEE3814CEC1893EBE3F /* Protobuf-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 75123AA17FF6CF721675F5EFB25EC559 /* FIRInstanceIDCheckinService.m in Sources */ = {isa = PBXBuildFile; fileRef = 44001909662AEC3C8F8AB4E8044AB034 /* FIRInstanceIDCheckinService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 756BA8556D315CD499501E923700528F /* GULNetworkLoggerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = E7BDF86CE64C4E407EBF8A73A20C6EF3 /* GULNetworkLoggerProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 75B139101E0BFF3585B49F931BE977F2 /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = 186880608DAD6477417FCC20081E68DF /* FIRInstanceIDCheckinPreferences+Internal.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 760970F7357E9ECCDFF141830982057F /* GPBWireFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 053874D026363AC0A03A09A01558AD61 /* GPBWireFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77399B95DEEE5E953DF7BADB4B7139D7 /* FIRApp.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D1E9800DF9216163D243A25E5A7E22 /* FIRApp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 776CAB01CC996B0FBA52C7C6872F0814 /* FIRMessagingClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 318F5854818D012A621F4EE3E8A310B3 /* FIRMessagingClient.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 786F3F286C9376BDF33F3008E351E6F5 /* OHPathHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 894FB1F3B5CAA20D3A8E5DA58FA415A3 /* OHPathHelpers.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7898A06A3FFC4228F5FC1CD65A7B8F94 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D6B1D921CE2EF324C684690E9B44CD4 /* AFError.swift */; }; + 790C5DA2D20D2290D35CD413F051C02D /* Shapes.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD38CBF4748B96190468E88F12A2064 /* Shapes.swift */; }; + 79D254191EAC73996F5BD06EFFA4E649 /* FIRInstanceIDTokenInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C1593407CAC28F4349FBA65B0C1BD9 /* FIRInstanceIDTokenInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7A746727440E0883EC1F855F0CBA10DC /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 773F43FA50FABF1CE0C562282F32D624 /* DispatchQueue+Alamofire.swift */; }; + 7A9842F18B9A92D8C8A029ED721E22B3 /* nanopb-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AD9FCFD914EDA9CDBDE1BA40686E48E0 /* nanopb-dummy.m */; }; + 7AB1BE129580DE43994C27204D3D9F97 /* FIRInstanceIDConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = A48A79CAAFF110C87DF8BF807837AB83 /* FIRInstanceIDConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7B9E46226BDFABC5A56EACCCAB550F13 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CFCAB771CD0ED282F14A09984871047 /* MultipartFormData.swift */; }; + 7BDE5F52B1111A7404B4B32EF8C5857E /* OHHTTPStubs-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B7A403AA64C0558925444F207EEADE76 /* OHHTTPStubs-dummy.m */; }; + 7C9F9297EAC2E0A5302B50564B575B0A /* Empty.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = B3B80947892AFE99F690D90E0E6F7A0C /* Empty.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7D4B4A11129ABEBE81CF0A75213D2927 /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D79D6EFCA519A3D859AD623DEEA3E97 /* Alamofire.swift */; }; + 7D8BB2A430E5C20AF8657A11C9F48016 /* LicenseFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B77C6FBEB46883FCDBBBF0333AAA959 /* LicenseFormatter.swift */; }; + 7D9390DFB58EAEF71DA1CE4E5F4AA98D /* FIRInstanceIDTokenFetchOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FD4F06E7B97586342DC5F130C93CAD6 /* FIRInstanceIDTokenFetchOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7E9687A54B05381DCB9BAAEA72366EA7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 7EAB3629AFCDDB950B9A4C610588D97A /* FIRMessagingExtensionHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC07246B7DD7857DA18E71CDAD1E01D4 /* FIRMessagingExtensionHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7EEA98DF6EA7BC488FC2C7DC4579BD86 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2207F5B391C14F1738C82A01AFB21DD1 /* Security.framework */; }; + 7F665E687CD8C311206F990CD0DA7418 /* Struct.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A62C867EDE3F5810D57F99ED04E9BA0 /* Struct.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8060AA86BCD21633E21A8DA29FD56D07 /* GPBUnknownFieldSet_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BE9D1869AAADCD42062E01D5D3C87C8 /* GPBUnknownFieldSet_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 807B6E3FF4C4A97577F4D5EDDDD49ECC /* Duration.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 5805433E9EE4075EBAE342A288525AD4 /* Duration.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 80975D2BEC9BBEB5D026A75D9A42B6B2 /* GoogleUtilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 44CE758ABDDC428058091BE3EF7C9451 /* GoogleUtilities-dummy.m */; }; + 816CD4237A652BDEADE317F1DD341A0E /* GULSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 47EBEF062D1954D670444D5FB49CB050 /* GULSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 817FFB25CEB300C681DBD8283FF19BA1 /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = C0865174F215EE5541472B794F16EABD /* SourceContext.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 82FEC2B074B1B137D892D51E72F583D5 /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = BBF0EE4B9DF20FB5E0DF535FED448A7E /* pb_decode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 837BDD2C7B095A5B3544B3B632ADA738 /* FIRInstanceIDTokenOperation+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 571718858875E6D21B448DAAA8A43D00 /* FIRInstanceIDTokenOperation+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 83CA30B037DEB0527448F9C54F396B2E /* FIRInstanceIDAuthKeyChain.h in Headers */ = {isa = PBXBuildFile; fileRef = CE04EB1BD0E0D76A2673A8C0C3366119 /* FIRInstanceIDAuthKeyChain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8494ADF872F49EA36C4844F0298DD498 /* OHHTTPStubs-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F6F1BBF9B142B5EF49F87D2D044E829 /* OHHTTPStubs-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84F2EA2BB1C1901EA0A3A1F71919F915 /* CGSize+DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FDAAF328CFC1916BD31D012F33FA11 /* CGSize+DeviceSize.swift */; }; + 857CEBBEB16312172E8DF03B1147377B /* GtalkCore.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 21518DB69A5249884D47AA1C030D65A1 /* GtalkCore.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8625F2607D15296CF239BC97F7BB3EE6 /* FIRMessagingCheckinService.m in Sources */ = {isa = PBXBuildFile; fileRef = 44A66697CB999F1B94BE112FF3F6082E /* FIRMessagingCheckinService.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 884A014FF635DEF5D4FBF2CED48D3610 /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F6EBA7C6997FF0B01735341A694592F /* Type.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 88E84F132638AF1A4D47AC5A0641131F /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = B7873C854D420CA53D1BD7CE0700ACDC /* FieldMask.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 890D4B46D1BE3870CA15607A41327FAF /* GPBMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B179EF2E474E501FD5650C4ADF83782 /* GPBMessage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8A3030124B1B48425552E80DADE1FA88 /* FIRDependency.m in Sources */ = {isa = PBXBuildFile; fileRef = FF710E85F020077130E558211B5B8D8A /* FIRDependency.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8A8D4BB3B21FE7CECDAA6908E6886531 /* FIRMessagingPubSubRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 849FE1C62D5BADA93D12508A10FFB88A /* FIRMessagingPubSubRegistrar.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8B512506674B51BA6D35237363F2B370 /* SDStatusBarOverriderPost10_0.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F243E68DA74E3EF1064781840A6375 /* SDStatusBarOverriderPost10_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8C435621C8561A336FCB112215CE7F06 /* GPBUtilities_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8466929A49CE3221978EB36183FD35BA /* GPBUtilities_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8CCB4DFC6700B70BDB65D48791A47479 /* zh-Hant.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B732E75D7C970C6F08CDE5C6AFDF8702 /* zh-Hant.lproj */; }; + 8CDCC6382693D52163B893E94EDE484A /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = BDF0BD64F7D053FC261E77000D9D5B27 /* pb_encode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks -fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8D1F1562F8784E50D8E14D44A8B915ED /* DefaultBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA144693E6BF8FE7CAC6E965241CE03D /* DefaultBehaviors.swift */; }; + 8D56B87617552C4649123F283D3F4383 /* FirebaseCore-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A78104E9B1CB747B9ACC895D21681C1E /* FirebaseCore-dummy.m */; }; + 8D67D48F9FE60EA4ECB227C7E5E988BA /* UIKit+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547CDF4449B3AF5D1990F54FD639448E /* UIKit+Helpers.swift */; }; + 8D769B1E75C52E3BFAC64ABA8CA438FE /* FIRMessagingLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = E2B37DD9690B667E67C7B749014FDAE6 /* FIRMessagingLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8D8C7DD544D90026F85550B2CC95CBD5 /* GULNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 71D265F83D526F8D4CBAF591F57A1C35 /* GULNetwork.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8DB74A47E65D6DF7F9632EA8709028C7 /* FIRInstanceIDTokenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B80D74D41E215EDC00F1A0D8245EC63E /* FIRInstanceIDTokenManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8E06E338A8F1324484A07E102C6085CB /* FIRMessagingExtensionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CFEFDB61382511167CBE5BFA016DFF7 /* FIRMessagingExtensionHelper.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8E1278F983579FE2CCEED68C625ABFF6 /* SDStatusBarOverriderPost12_0.m in Sources */ = {isa = PBXBuildFile; fileRef = CC67002EE29757073391E2064F1BD0E6 /* SDStatusBarOverriderPost12_0.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8E1D665623C95E8500B9B69BFE963089 /* IndexPath+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6605561032963C6225A616C84441A72F /* IndexPath+Extensions.swift */; }; + 8E307CE212F087956B2835C792FFC79C /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E629EB70356C8FA1AD9781584EA8374 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-dummy.m */; }; + 8EC15CDA263AE10AF1D49B82794AFBB4 /* GULNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = DC604E06843C199B7238C7ECCDD65231 /* GULNetwork.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8EFC6634D956643DB4EB307460CE67D0 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A10B633A7F6F7DB8565FCD54B2F6015 /* GPBDictionary.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8F1FF94F0311B30034EF2698971AD690 /* es.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9917CC431DC36BB3D118B1AA7A204319 /* es.lproj */; }; + 8F7F70BA374635820D060762A15931D3 /* SDStatusBarManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CD626DB394FDD0FF51FD012D20A334F0 /* SDStatusBarManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8FBBD77BDF34DDAA858E757318F1FAC5 /* GULReachabilityChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E3AE25C553C268ECABA7BA60383152 /* GULReachabilityChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8FD25BB2E0968A8C1C27B4383552FB40 /* Clamping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526F1F36C6164054C3753D3E4D5C5C6B /* Clamping.swift */; }; + 90CDCAD92FF576BA1E27CAC55DF10C91 /* FIRInstanceIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F00E32E42A1E8D5237611B57EB97BFC /* FIRInstanceIDStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 917E9C7AF939B0FFD3C026BB4EAC73DF /* FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 677C759A60BA1A68EC54588ED16024FD /* FIRInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 91E15F3267E641CB6282B424CE389263 /* ko.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1683A78B7B9007625AE95AAE42A96663 /* ko.lproj */; }; + 922299C14975D3257CEA7CD05B8230AA /* FIRMessagingRemoteNotificationsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = E689A6FA791FBDA83E75CA835495CE84 /* FIRMessagingRemoteNotificationsProxy.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9243AFCD79CC422AC3AE16E6CB0C262D /* FIRInstanceIDAPNSInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 046CA33B599DC985AC83516113232E99 /* FIRInstanceIDAPNSInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 92716A0085066BCCB43369069E76403A /* GULNetworkURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 8239448521ADE6944ED02A4E4E8F83C5 /* GULNetworkURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9307183A631102399452F35E8630D4C1 /* Priority.swift in Sources */ = {isa = PBXBuildFile; fileRef = 968AD6C6067177F3FFBF4E22B5D62AFA /* Priority.swift */; }; + 9335522C7018277CE54C18E182A5A1F4 /* SDStatusBarOverriderPost9_3.h in Headers */ = {isa = PBXBuildFile; fileRef = C40BAC08597BADB1064666DF2633CF2D /* SDStatusBarOverriderPost9_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93B158CFAE0146108F8D3DF1F5DF2FEE /* FIRMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8948FFD9D354F2001C98CEE8B45E08 /* FIRMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93F97DB70699CDB8C433DEB03991621E /* GPBUnknownField.h in Headers */ = {isa = PBXBuildFile; fileRef = 58BC5AB95FAF621615835A4436B69D8C /* GPBUnknownField.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93FE3279105620965FABBD2F6D30ADB1 /* FIRInstanceIDVersionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0940BB70F444E65F6DB52323B97369 /* FIRInstanceIDVersionUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 93FEDE6C16994FA82F27CC56168013FF /* GPBArray_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = D9011FC16F020AA7453970FDC70281F4 /* GPBArray_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 949E82C19D7A44BEA21AE96476C2E533 /* FIRInstanceIDBackupExcludedPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = B8D3618FE4C32D4ADBE22D247745AB5F /* FIRInstanceIDBackupExcludedPlist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 94E0EEAC1123DEFF7625B88F0E71E3E9 /* FIRAnalyticsConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2C2A90AABD3780C5969C4B208AF34F /* FIRAnalyticsConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 94F0EFD969D064F5D663A6EE835D4516 /* FIRMessagingDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = B8E0195AADB4B77EBBA26DCB16A7ADB1 /* FIRMessagingDefines.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 95C6E0D347DA6F768468BF0929F8A84C /* UIView+KeyboardLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 365D0C4EEEA6C8DB030220CF3E73772A /* UIView+KeyboardLayoutGuide.swift */; }; + 96468709B156DCAC50DABCA9CB197F21 /* FIRMessagingRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 5725B7F7891756CBC38A7C3FFBA0605D /* FIRMessagingRegistrar.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 969588515E0889063CB93DA45160D18A /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = E82C57A8834CD3A374E5E52A9DEBA80E /* GPBUnknownField.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 97C1EB978E9BF15E1F44EA79EAB899E3 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D3E35ACC5108C1B4DEF24DD53900541 /* Keychain.swift */; }; + 9811AF1663228E41A0F9116F3FDAB4D3 /* FirebaseMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A68AA6C83230BBFED7CC97DA09A987B /* FirebaseMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 988E2668D29D51B8304BC24235BA15B6 /* FirebaseMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6FB40F4F28DA6BC422DDDDBBC7CDA6 /* FirebaseMessaging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 989554E915C48AB0868348384AE545C8 /* FIRMessagingDelayedMessageQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = B1EEA6318B7652582ADC0248EF0E862A /* FIRMessagingDelayedMessageQueue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9895E36F7164AEA6EFADE585598C4B9F /* FIRIMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = D46CD8B2E3B48A9900B0D54DC022F51E /* FIRIMessageCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 98F45B8FD93C9BF709915C0ACC7D316D /* DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC35B00BCB6D00D5DC095E60BA6F8D5 /* DeviceSize.swift */; }; + 9A7E0722E552D06D26AF4A48C0FC02C7 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 536F55571CB5D4E8C4CD313EFFC98897 /* GPBCodedInputStream.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9AEA26145F40861CBB60CF404C36C469 /* UIColor+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = E036B66F0200BB21E6A3C50B4A98D7C8 /* UIColor+Helpers.swift */; }; + 9B713E8E0EFE0EA70A995827E5394683 /* GULLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D1AB7F35E8D9D69E2A3E30D0AFA1F1 /* GULLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9C24AF3D249563A26F59EDFBA4C7773A /* FIRMessagingRmqManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BCBB2D56D50E44BD77F0169A7F75E7B /* FIRMessagingRmqManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9C27962A6C09FD001BE83B3873C40856 /* FIRMessagingAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 98DE82806BC35C7A7C3ACBCF0C7B379F /* FIRMessagingAnalytics.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9D37E82FFBA10D1CAC0BE6FA8C3B17E2 /* Compatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE96786D662F36B014DB2976712E52D /* Compatibility.swift */; }; + 9D86C6E7427763F4CC75403A37ECB547 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + 9DD886828EFFBBDB2439ED4B11CE081B /* SDStatusBarOverriderPost12_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 322AE82498430F3AA39C51C2BC4FB15F /* SDStatusBarOverriderPost12_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9E2AC1BC432B98F9B748D05D7B488CB0 /* OHHTTPStubsResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A3F12E1757587C015AB1F285348CFAB /* OHHTTPStubsResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9FBAB5AB3AFE3F48C77BAD0033828124 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + A00E351731E9CCAE152C5B88D885F776 /* en.lproj in Resources */ = {isa = PBXBuildFile; fileRef = DFDA0DE503139F615A5FB983A7BAFD1A /* en.lproj */; }; + A0A162DA5D4BB9A0DAFA3B60DE55130B /* UIViewController+Lifecycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA99AA3900C0A75CF6AFE7E2BEF2A0 /* UIViewController+Lifecycle.swift */; }; + A0DD808CD41CE6A758A3C64289598B2F /* Anchorage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 031FC7BA2605BE0368D9692DBDC15D81 /* Anchorage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A0F9B76BF94A692BF96E87085472F70D /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 37D1089A0FB89C55B768CC26C804A7B2 /* GPBExtensionRegistry.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A142ABBB6E27723CB76393007499BBCC /* SDStatusBarOverriderPost10_0.h in Headers */ = {isa = PBXBuildFile; fileRef = 76848D31B6A54F9167B3E81B2B157273 /* SDStatusBarOverriderPost10_0.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A18D4637F3EB0E9D08ABB14CE34737CF /* FIRMessagingSyncMessageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B7A5E48BA4D6DE7CABBE36B040019834 /* FIRMessagingSyncMessageManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A263672C857DB63F9F371F1E52FDE51A /* BetterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6B719E9A14C1E430887BE3B805CDDE2 /* BetterButton.swift */; }; + A2C760AD1904241031DE9DDD5DB0E935 /* GtalkExtensions.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = B4C8749E960A855A7C7965EC2BA8218A /* GtalkExtensions.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A3492135E0BFF1F6BE2DB3BCB52907C7 /* KeychainAccess-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EF45F089BAE93FE828CD9688AA8CA8A /* KeychainAccess-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A3A7C1C339F3BDCF7DAE115107D4FC89 /* FIRInstanceIDCheckinPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = E2E3405DF921FD6575E7698CA8B86D62 /* FIRInstanceIDCheckinPreferences.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A4D4A302AEEB0666AEB08B226637D78E /* FIRInstanceIDTokenFetchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = FD58305059DB6EF784EF634B198DD3CB /* FIRInstanceIDTokenFetchOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A5F185E6FD5C3BBCF46BF62774965E31 /* FIRInstanceIDLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = BAEE38A7456029D2435589A2AB61BB54 /* FIRInstanceIDLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A605E2BA73843B1BF04318D1F249E7D8 /* FIRInstanceIDKeyPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C526BDE19AC726B077CA91F4A3D248 /* FIRInstanceIDKeyPair.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A6413A77105FCE014808660C4A174018 /* FIRMessagingAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AAD5AF881A90E6C8ABB964271CD3D7F /* FIRMessagingAnalytics.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A6DB0753F4D2BE9056C288F6376CD092 /* FIRComponentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 990D5BCA382BD9D9D2C3C1E291F2B135 /* FIRComponentType.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A7140404957904FEA7F3949F01B858C0 /* AnchorGroupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F6E205211513A677E520BAD5BD8C183 /* AnchorGroupProvider.swift */; }; + A7A6BF0C62BC3FC2F757468C317099EE /* FirebaseInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D5C9E49FD0B96CC5F0A774F637668F2 /* FirebaseInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A818814179D868596CE5F1BC13302BB3 /* GULNetworkMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 35D0212C3DBD3EB9B48F92FE6E705124 /* GULNetworkMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A85388EF392B19C59DC3C5F54AE550BB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + AA174969F3D235A0D986C40FA01F8696 /* SDStatusBarOverriderPost10_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 21921F807B4B34CE95F4333954EF9330 /* SDStatusBarOverriderPost10_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AA2AA7707B86A60F4E9CCA3E1BE504CA /* GULReachabilityMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B6B0B82C4B090FD5CCE3E4B3185607 /* GULReachabilityMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + AAA60349DF99530BA4F476C8D9DF2AC7 /* FIRInstanceIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF524EA9012A4ACFCAD0BF6C7247299 /* FIRInstanceIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AB7B824DA74A18F8F235023186B0CB99 /* FIRInstanceIDKeyPairUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C5090975983CFFFD9CB40E0075C0D038 /* FIRInstanceIDKeyPairUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AC38CF40E73B97EFAB79BBE6B56C8731 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = D362F402CE5684297570016D7825F239 /* Request.swift */; }; + ACF4FD5B728533D8559BB12F6428EC2E /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367EF090BA9D626CCBE6C72374BAB47B /* ParameterEncoding.swift */; }; + ADEAD2F9475DADEA607C02D303956EBC /* FIRMessagingPubSubRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = ABF027D832F3CFAAE988298C13DB25CF /* FIRMessagingPubSubRegistrar.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AE1DA43BC4C87D79899149013C1DAD98 /* FIRMessagingDataMessageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E735845AC66A0F18361E9CB0A620082A /* FIRMessagingDataMessageManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AE2FB5B79FD2943549EF53126CD94862 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C4060169D4E6873CF1EEF2A457AC3BD6 /* GPBUtilities.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AED93C5125D8ADFC97325BC4BDEE8F53 /* cs.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 74BE747D93A2FF0D9596DFEB89B88506 /* cs.lproj */; }; + AF9BB102EA05092BA8BAB13BCA806CEB /* tr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = AB8C0F48EBA2E62C0D0D696427AAF734 /* tr.lproj */; }; + AFA19EAA3DF13F4E416F836CDE2C1251 /* FontInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E07B09F7C15576A3A444C774F45026FA /* FontInspector.swift */; }; + B070DBBE6F946A656405E140E975A211 /* GULAppEnvironmentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 5439C399E40C811A0CC58CD80BF419DB /* GULAppEnvironmentUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B075936A698C95B193BF870AF0C5DE9C /* GULAppDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 60057B688B56F5C62D15997BB9EDEFDD /* GULAppDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B1169761CF66CB7C48BFF5F13A2A89A6 /* SDStatusBarOverriderPre8_3.m in Sources */ = {isa = PBXBuildFile; fileRef = 433FD3F0C39CB9CDDF7F51F624242518 /* SDStatusBarOverriderPre8_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B1AB9C0D1668DA7D1FB8B05625FE15BB /* NavBarHairlineFadeBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 441C8E5411061099355CF78039DCB16A /* NavBarHairlineFadeBehavior.swift */; }; + B21176F4F4CEC62BCAFC4FEB1712C2B6 /* AcknowledgementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF86C6514C399C0918A89B10C69289BA /* AcknowledgementViewController.swift */; }; + B26BD92ADC60A9F477AF155252F41C61 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + B2C05E981C8FAAEA0F53F712918CBEBF /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D75377169BF1143EF206F74484FC1F0 /* Timestamp.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B39604A46A4903C262D18E317F1E6C6C /* FIRInstanceIDKeyPairStore.h in Headers */ = {isa = PBXBuildFile; fileRef = EA44C89EDF2C4365821C353514E832DF /* FIRInstanceIDKeyPairStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B45A8A82A0FD4C548C6DB743E8095E86 /* SDStatusBarOverriderPost8_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F88E4F0E3A11E9B5D721DEEDEB2F09 /* SDStatusBarOverriderPost8_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B4B77955EC2C522E041EBA397F87FE65 /* GULReachabilityChecker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = EFBAAB841881AAAD3B071BA31361B288 /* GULReachabilityChecker+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B501012C85EBF16411A4B9CF856A3044 /* BonMot-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F7535A4C380C47E118395A613AF3D849 /* BonMot-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B563C657D3678F851A0F8881DC90DB25 /* Compatability.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF22CC9C8607DFE61523790B4E8080FC /* Compatability.swift */; }; + B5E3F3D139F7AC7686281E983CAEC0B9 /* FIRInstanceIDUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB3FA695D6D0C669DA36186435E474 /* FIRInstanceIDUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B60414F93325024469AAB0F4B1D4141E /* FeedbackPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6228C304CE54B8A03AEF3954707FB619 /* FeedbackPresenter.swift */; }; + B6D9136FE482A5716B99CAE6FF7545F4 /* GPBDictionary_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D7113D1B1F68315334A5D6E5C78151A /* GPBDictionary_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B734B64212F2A039FCAC85F14608AACA /* GPBExtensionInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 780F31022D4CCCEEEF6B0433A8907F93 /* GPBExtensionInternals.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C5257CFBE55442EECF051DF82E729B /* FIRMessagingReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D090276832D4024D8B3A5568BEA4DE /* FIRMessagingReceiver.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B9AFBB66C67E71F0BFDD0DE5687C9CBC /* GPBCodedOutputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E6D0C984DDF42A7E6B78C3EAE3C981CB /* GPBCodedOutputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BA0C33AE7563904D128CB643510CCBE3 /* FIRMessagingPersistentSyncMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = E19C54CB57055FAC1B7EC1A332B36AE1 /* FIRMessagingPersistentSyncMessage.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BAA7A298BF2D071AE6077551CABDA17A /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A99BF2E906BA57B9D716EC2F28447CF /* Log.swift */; }; + BAB7813CCBF7A137B84D0EAFC620B6DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A467A3E9E3137B15241AA445AAA69D3 /* CoreData.framework */; }; + BBE95066A8DC1C8D8CC907000D70541A /* NSDictionary+FIRMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = BE03FBD1AE757BEDE8D7B21466965FD1 /* NSDictionary+FIRMessaging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BC256D583C7221D6FE3DC13F08C02FEA /* GULLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D45D29B213853B66B8B282991CCF083 /* GULLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BD9628048902C3E6580C8916350A4EE7 /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E5D20BCCFC283EBF43CD654944F92FB /* Any.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BE2C9A27C741D9C0773B4037E0D68B57 /* GPBDescriptor_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 399A0F9FCF8F163E53341ADFC13A530F /* GPBDescriptor_PackagePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BEC7476DE1CF263A31FA893D2B2A2E70 /* FIRInstanceID+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 10D13A0F900275F0E08660D22CBD3BD7 /* FIRInstanceID+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BEF4756AFAB837E4497F73F05DEDEECC /* FIRLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = B02CBEEE2EAAE48F5C59A0748E149382 /* FIRLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BF4C76B8E0C15E7C2A4762EBB84872F0 /* Wrappers.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE6952B80D386C75EA01A7B003A923F /* Wrappers.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BFD1F6C176B28F48CCF2BA6577A6C170 /* FIRInstanceIDTokenDeleteOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 78277DF682670FCB6D1E611B6DD72010 /* FIRInstanceIDTokenDeleteOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C1676FB1FF537AED93DB44C1582AC152 /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = A23C1F66FE104A9AB25DB49ABA41F52E /* ResponseSerialization.swift */; }; + C19BF82AAEAC7AD417C728F4C00B58CE /* FIRMessagingVersionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 4707DEF6F61CF955E8D0164566D43983 /* FIRMessagingVersionUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C2158E550AEB96660AD13D089D75543B /* OHHTTPStubsMethodSwizzling.h in Headers */ = {isa = PBXBuildFile; fileRef = DA1CB779343A19D8C026EA3A9FD492D0 /* OHHTTPStubsMethodSwizzling.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C264488148DA19FD69AD0378C76E7DB9 /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = E274690FABF5774F0512B21622B9BAD0 /* GPBExtensionInternals.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C289B85A33500EE2453F08CE5D0DB7EC /* GoogleUtilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A64AD290563189B5EC09536986EEA27C /* GoogleUtilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2DFB45D6494E63C9993006A15DE55B8 /* CurveProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88DB8688B47BE7D71F76B016AD52DA8 /* CurveProvider.swift */; }; + C329C3A3A838C4AD86611F67A10BFEAF /* NSError+FIRMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F619742AF64CEB785C8717E281D3DA7 /* NSError+FIRMessaging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C7EC6507F6038550A48154729F095B52 /* de.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C8268059830026F500EAD6383BB19F88 /* de.lproj */; }; + C8A5AA38971136EED1E4BC61205A591B /* FirebaseCore.h in Headers */ = {isa = PBXBuildFile; fileRef = CEC8FF8EB54F243F318CF7B7F16F7278 /* FirebaseCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C8AC529DAADB07541D2D33E392CDF169 /* FIRMessagingDelayedMessageQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 468332F23F5D358DB2288F3934AEC350 /* FIRMessagingDelayedMessageQueue.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C8BF91ECAD3BF591B752B6C3BCB6761D /* Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA2C241BE9B8942C2622A8288159183 /* Internal.swift */; }; + C9157A5A1365EB4A1D49EC2E8619E4F7 /* FIRMessagingTopicOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 88C8386A2D3A8315518D7FC2CF01A15B /* FIRMessagingTopicOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C92E53E0F9CE7D32CAEE125353487361 /* FieldValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2FA012779DEECE2BC6CC90C6E90407 /* FieldValidator.swift */; }; + CA260A0E0878CEE776DE12492DF46949 /* pb_decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 322D077B4897B4E6A8C083170A121575 /* pb_decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA4CD125AEC29FD189D003762B57494A /* OHHTTPStubsResponse+JSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 247C04FA03FB22629ED9C337A195F8F6 /* OHHTTPStubsResponse+JSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA601EE9EDA47E65195D3BF43930A270 /* SDStatusBarOverriderPre8_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F937168226D3E9CD0FDFCA1B32629DA /* SDStatusBarOverriderPre8_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA9D644E80935F7226B7D7105E837792 /* FIRMessagingSyncMessageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B4625D667AFBD9425C3A79449E05F451 /* FIRMessagingSyncMessageManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CAE0EBE0C0215C8BD9ACB0BD0562526F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + CB0F1A83E1DFE29F971867BFB285B59D /* GULMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B5E83DF94AA1871CCE123E6D44F0B70 /* GULMutableDictionary.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CBBFF56D23D20E974E5D8DF04EF3637B /* GULUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 807724545CC9FBB3B33672198DD057ED /* GULUserDefaults.h */; settings = {ATTRIBUTES = (Private, ); }; }; + CD780A5F99BC76FD2C51EEF2E495CACA /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD145FCE40536EC56F550EF22AE3A2B3 /* GradientView.swift */; }; + CDA29493785FE82167BBBD3348DFB2D5 /* ContextualAlternates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2707310D83A1EE6275AED80C0CF694FE /* ContextualAlternates.swift */; }; + CDE4C38B065973A40B8B7C844D236F86 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */; }; + CE60B4B85D17A08CA721EEE416CD1C83 /* GPBCodedInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D827CD1FACB9020945F3B62976196F5 /* GPBCodedInputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CE8F8AFEE45337F90EBA0EB35A82939E /* FIRInstanceIDCheckinPreferences_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E28DADD6AFEF6A2BABCAA95C90585AE /* FIRInstanceIDCheckinPreferences_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D0015B5606D3E07958B6F40D8625B8F0 /* FIRInstanceIDKeyPairStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 13811593551EEF5606EAEAC864156243 /* FIRInstanceIDKeyPairStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D05BF98677EB4739C37C9533E8D877A0 /* NamedStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 288D811BFAFF4D05B72871868528971C /* NamedStyles.swift */; }; + D05E35FCFD0AD588208B9A3258ED8F9C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + D08829137C1C28D74067CE0D2C9EEF00 /* UITextView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2765A7D6EF27B9AB42D6279A14D1669A /* UITextView+Extensions.swift */; }; + D2801FDD33B72D4C72A170C413AA7D71 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 814B71C2E085A900096EC6AECF6B4CE3 /* GPBWireFormat.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D3044F1325FD2E1F21B84CB5E9F5CD86 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = B2127ADF7134D22A7B41243F58B119B2 /* GPBUnknownFieldSet.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D33AB83EB8EE0B969A5F68BAF790EC60 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 829A957DF3BA4C53A538E446773D71B8 /* AppInfo.swift */; }; + D3B02CDBEEA6CB4AFA124B0D8FA73C06 /* OHHTTPStubsSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D5703DE6D32E8BEE77AC1C2A64D12F /* OHHTTPStubsSwift.swift */; }; + D448F684FAE5EF02A10E467A097B2B8E /* Any.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 22D1FCC1043B4DD3CEA939877906ECD8 /* Any.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D46809D86D5BB4EBB9AA10F29979A860 /* FIRMessagingConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 360D12ED7F2D4981DBE39DE4FCDC76A3 /* FIRMessagingConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D47C36356662BB1CCEC086A9339876E0 /* TintedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F5BB4D560F726BDE1F35DA184B1268B /* TintedButton.swift */; }; + D4EB284204E633D9175B0D5D850EB0EE /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = CE3DE9896DF364A9A8E70FBF3411CAAD /* FIRComponent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D560EF907E1B219904938C32DCA07877 /* TableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245165C00B0AB8EFA8DF3D2BBC1F3C8D /* TableSection.swift */; }; + D6F46C2555BF94DD17EB5C5137297B7A /* FIRConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B7024F62947EF6E2C6FB6CD5B34E2ED /* FIRConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D7B354F43D71BF171E85F1A3D460C027 /* FIRInstanceIDCheckinPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = F7515C947EF6212592653822C53CC690 /* FIRInstanceIDCheckinPreferences.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D7F5B4B7FF371A59B9F5625EC8ECAA7E /* FIRMessagingConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = AD183A51FD1FF965003291AC5F048C14 /* FIRMessagingConnection.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D8342F77FCB434AAD8975E0386F61252 /* XMLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1C7DAA26B8EA104B1A50DE2EC3AF35 /* XMLBuilder.swift */; }; + D86369D98CDF2CD116CBC4B66B089CEB /* Api.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = C392AFDD980E1C6B8554B9CCE3D4F95A /* Api.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D8C1006C39A3ED7B8F0EBF65D2E66303 /* Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23F5E88F86F777E70C48C646149BA42B /* Transform.swift */; }; + D9D8875B70BCDA90E099D5BA8A43A802 /* Compatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FCB1518EBBFFD314F997C63F2AE720F /* Compatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA1DCD65BFC20A27214C1138C1B92D7F /* StylisticAlternates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33CE071F3F3081B71DA145EC68A99E8 /* StylisticAlternates.swift */; }; + DA40FB231BD634D57A958BF90B7D27B0 /* FIRInstanceIDVersionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = E90EB60C7D8B2CBCC777305E2D53F83F /* FIRInstanceIDVersionUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DA5908E1CF98667FAE1CBEC76D355CA4 /* FIRAppAssociationRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = F0821896A90AE916F84B3E580249644D /* FIRAppAssociationRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DA8774937F99D03BE90B136C8A6A3C55 /* SDStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 65DFDCD7CA8EB72916D84A809A50C7FD /* SDStatusBarManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DBC85A7FC433639F2460B8ACA3A55882 /* pl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 842142B2B14A0BA4AFCC17CBAC0F7C98 /* pl.lproj */; }; + DC5DA57E4485C2FC85FDF53428C747DF /* FIRInstanceIDURLQueryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E1E27256DFC0F8898600F8DA01A1D3E /* FIRInstanceIDURLQueryItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DC6F351B5AAB3C9A2D73772E8BD102B6 /* NSAttributedString+Adaptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A4ECCE028DEB376DB17F98A1E4451E /* NSAttributedString+Adaptive.swift */; }; + DC7608F13970D10F8031C34305B4E2FB /* EmbeddedTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B74880F26CD1B4204F6539C5B5502D2E /* EmbeddedTransformation.swift */; }; + DCE2544D0E3CA203C5FC20C01510DDC3 /* NSDictionary+FIRMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = BA59223CF8122E668F27A492727DA05A /* NSDictionary+FIRMessaging.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DCED874D6F57DD0E744C345B53E96C3B /* OHHTTPStubs.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE96B90011674F188BAA0598BD91B53 /* OHHTTPStubs.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DD1C25E78F7402AFE7D53F6CB0EC6459 /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4A5B8EBEA544128E7C93E89A933ACE /* GPBRootObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DD34CF52B04302F2F486A626A57EBE9B /* FIRMessagingPersistentSyncMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 356BEB97A3924CA7A9EFA6E39B529298 /* FIRMessagingPersistentSyncMessage.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DD904DE0D282B9A9724B76536A085559 /* FIRMessagingTopicOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D0CAF61CDA366988A208A7B3648AB10 /* FIRMessagingTopicOperation.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DEB02DD77A9565F861100EC194EA6E99 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6010A7276EC10495D966DCFE5E3C113E /* CFNetwork.framework */; }; + DFADB7B9266D1032D5BF21F2F1D02D96 /* pb_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = E862D618BF042EA8A06C94B566412A7A /* pb_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E052E19761060467DB062D60D88F5536 /* SDStatusBarOverriderPost9_3.m in Sources */ = {isa = PBXBuildFile; fileRef = AD7C3AE346CDF47C559CAA1E29D38819 /* SDStatusBarOverriderPost9_3.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E1355ABFA24FFFE7788FFC23A0E5543D /* FIRMessagingSecureSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 67D20FEE4726CCB26A931435C6F7F8D6 /* FIRMessagingSecureSocket.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E1797B933E4A716E831F34EFC24F2A18 /* FIRInstanceIDStringEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 24FEA1649F859C025807618A170C83B1 /* FIRInstanceIDStringEncoding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E1C7D68DBCE3516AFDBB93D344E4710D /* BonMot-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0055556FD5940D94B5719D2CE306ED83 /* BonMot-dummy.m */; }; + E20902716A8AA163A00FC6FE3817D4C1 /* FIRAppAssociationRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0245E1DD96C5A71E0976E257585FB875 /* FIRAppAssociationRegistration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E237EA812A181AA46ABC963AC29854A5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + E27438C8E65CF4DAC905C6026EBACC35 /* FIRInstanceIDLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = B348867894A4CE1D01EE3407670282AA /* FIRInstanceIDLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E2B5FF0AD096653DA71FEF1BBDC6233B /* ja.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0F5EF93A5BE453909C31B9C6554C95CD /* ja.lproj */; }; + E2C7E5A5A237425DA4C72EFF01475076 /* FIRMessagingUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D7DEB68026091907EB2EBB5D82C47A00 /* FIRMessagingUtilities.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E2E71589715B273DE6163D5FB435592C /* SDStatusBarOverriderPost10_3.h in Headers */ = {isa = PBXBuildFile; fileRef = 1997495D70A0AFDD3D4437EFFABE3048 /* SDStatusBarOverriderPost10_3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3A6BE04CAE18910FF90BC707A1B586E /* TextAlignmentConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5112CE97A821E9C641D75D1ADAC3EB32 /* TextAlignmentConstraint.swift */; }; + E5C352E6C1B3288A651344F557E2A10B /* AdaptiveStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E57EB3CB3312081676A46F7238B24 /* AdaptiveStyle.swift */; }; + E75E3A02BC9CCB56D1671F7FDCB1D543 /* GPBRootObject.h in Headers */ = {isa = PBXBuildFile; fileRef = BB5DFE1F01AFD7800F073ECA808AD019 /* GPBRootObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E78643D19759C84B84FA5C437DD5C285 /* Tracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD6721E414F5E4895627210AFB5397AC /* Tracking.swift */; }; + E79E53BD4BED86182EE57B0E7D1FB563 /* Composable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D93E1401B7CC5204F8F2112E6F2DF1A /* Composable.swift */; }; + E851CD56878C963DD7E0CD660FBE4D22 /* FIRMessagingCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 986EF3488689CACCCB183285A1909D6A /* FIRMessagingCodedInputStream.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E86C0147FE8704C88040B0AFEF4E7648 /* FIRInstanceIDTokenOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F5FE5A0393B7EA11DA9DBF03DDF5479 /* FIRInstanceIDTokenOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E88203FD8E2B01EB71219367D94608D0 /* FIRInstanceIDDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C8877C44A2A9CEF55FFA4B756AB34A /* FIRInstanceIDDefines.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E88F998AF2E3FABE07308B1454182029 /* FIRInstanceIDCheckinStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 0904254547F200171C92FAE60BF75E4B /* FIRInstanceIDCheckinStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E914909867188AF11D12A4292BBC9729 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 8942E740881A6372C900E36D68EAF4CB /* GPBCodedOutputStream.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E93C17002FD7C60CDD5B227371E6AE34 /* UIWindow+RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A6E8BEA17526E69B7E7C440D290E2 /* UIWindow+RootViewController.swift */; }; + E985433DB346442DDCB5F6E16CE7D280 /* FIRMessagingRemoteNotificationsProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 7240263E6AB16234AD51BABC7BEDBFD0 /* FIRMessagingRemoteNotificationsProxy.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E98CBA7CFCF3D96C5B50770A4D3517B5 /* FIRMessagingPacketQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F9E4B9D5FF21ED1F4AB75BA5BA13598 /* FIRMessagingPacketQueue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EA4C0FEE83B95FA4CBD6A1C7A1041CCA /* GPBProtocolBuffers.h in Headers */ = {isa = PBXBuildFile; fileRef = 789045C4CD88187B1C8B6952AD65877D /* GPBProtocolBuffers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EB3DC0691CBB0AF117F1D9D442FA67AA /* FIRInstanceIDTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 661D315940B1DDA7A83242BBBB7CFCA3 /* FIRInstanceIDTokenManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EB9352F06FF1E5906D9D91135967ABB8 /* FIRMessagingPubSub.m in Sources */ = {isa = PBXBuildFile; fileRef = 949C61608ACEFB9BB47A141E428D5CED /* FIRMessagingPubSub.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EC29582AC7D6FAE74A58A4795B136544 /* pt.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0172526E6D3CEFD172AD72474B7F1B03 /* pt.lproj */; }; + EC85906F2F06B19325232E7A96846CD3 /* OHHTTPStubsMethodSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = B0DF923FAF38D4B7E93295F4F7B7E252 /* OHHTTPStubsMethodSwizzling.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EF6D8F4A474E5287ABFAE4449F45C827 /* GtalkCore.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D36157D372B866FB49CE4288D881E3 /* GtalkCore.pbobjc.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EFE7887C3624E7E6BA06AECB489778FE /* NSError+FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E542A623F5A954B3F4D243CF8A4FB46 /* NSError+FIRInstanceID.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F2C4A6F7AC480DEFAE6217C46C05E974 /* GPBExtensionRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF32B5609DBC1BE477D33A94686964D /* GPBExtensionRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F36D0E75366326FACC9EB8DE7F4F98F4 /* GULAppEnvironmentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C3BE33C9694478A1505C09DAF4276BAA /* GULAppEnvironmentUtil.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F387A6A0B4F0712AB31A31AF06E1437D /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FA78D05699B3A7B758DCA452BE2C72E /* MessageUI.framework */; }; + F4D84858653EFDD2A8738A28176A44E4 /* FIRMessagingRmqManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 92F4855C80835F853383873CD1CB78B4 /* FIRMessagingRmqManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F53A883BACBEF618EB01165812EB60A8 /* FIRLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 7902953F39F914B13DAD07D6C494973D /* FIRLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F56B615204B36C3D1287663301D9ED63 /* AttributedStringTransformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3D53C87F3183ECB9828E9F2CC13CEF /* AttributedStringTransformation.swift */; }; + F5770C14010A6EA5DDF6D28111858B75 /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D735903962EFF3FC6A7517312F923CA /* FIRDependency.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F58012B0BEE8E73287F2A68FEDAD92B2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */; }; + F5A597E46D8296D2C414626E7F99C0EF /* FIRInstanceID_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F4E12C03F40438969454920C49D2013 /* FIRInstanceID_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F5DC2F62DE6E7D1D2166347768660F62 /* FIRInstanceIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F64FB46C163A2D7EEDD531525ED4A3E /* FIRInstanceIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F628B678C1D14102D5A6B8E8A369F7FD /* FontFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF280833555D9A6C3AB807C1BBEF193 /* FontFeatures.swift */; }; + F6F184A43AABC119977DF12AD2ED2053 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F63F7236794D312ACB1F32E2BE55CA4 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F6FF11572A5F8C02E4BA95CD335737E6 /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 809A9FA0958DAAB72D85475C1510B28C /* Api.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F751BBA11B2C9DB683D3FAC54D1B54EC /* GtalkExtensions.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = D5EB134AFDFBA28F3347C088E94F3AA1 /* GtalkExtensions.pbobjc.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F7CA527CFEF6E3DE6466C6D66D138346 /* FIRMessagingLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1500A31AAD61B6B55D1541CEC1F8B821 /* FIRMessagingLogger.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F8E578B6F9EE4FDDEDF54894A8FCD15C /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FA9AF149F192E34E86DF398F93B6819 /* Tab.swift */; }; + F9956CE423EE435E6B36C133CDD5D27B /* CGFloat+DeviceSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF40060DC0344F915D924D3DC88F272D /* CGFloat+DeviceSize.swift */; }; + F9A8B355EC256F8B149021EB7C0F8998 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 8487A57EC520F91735649B13CF1455E4 /* FIRInstanceIDCheckinPreferences+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F9B80E71A9F0D909B1F73CCD753CF53B /* FIRBundleUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F6CAA436B21A9F893735228C041394 /* FIRBundleUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + FBA2DE155485C184B1D2D04B60B5F4F0 /* Swiftilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 016ABA6E4EC051693A5A08A27FAAA7DC /* Swiftilities-dummy.m */; }; + FC6AFA3387CA425C566B007F0EA9B9A9 /* FirebaseMessaging-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C9AE3F8C3C621FD1D0196F941D21A520 /* FirebaseMessaging-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FC9D03E94B1D4725AAA52ED0AFD5463F /* FIRInstanceIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 3739B5667A1C1B8452C08E5FB55014E5 /* FIRInstanceIDTokenStore.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FCEF602D4650E2F192CE13FE12DE83CE /* HairlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9435CEF7CA7BCE866E215F71262E51F6 /* HairlineView.swift */; }; + FD8EAE65C4C2FC32FE51494D63D4D180 /* KeychainAccess-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F140B1E39A706719A3E80EF3EE95186D /* KeychainAccess-dummy.m */; }; + FF1D8B1CA0865B7484F0874C6517D3CD /* Timestamp.pbobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FDE57075083813209769DB1ECBA097C /* Timestamp.pbobjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FF7B4E979DC08115710FD5CF868DFABF /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 38337959621A4D9065BD17ACB25371AD /* Wrappers.pbobjc.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-all-checks"; }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 02B643491EF1939B6406629306F2675E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + 08148E3EFA12C37CE29E49C3C7EF9167 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1E798429DCFA7906F6625CCFC1088744; + remoteInfo = SwiftGen; + }; + 0C1025B53BD27B110B05E793A41AAC91 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D372E53E2E8FEAA06A0439FB85E65767; + remoteInfo = FirebaseAnalyticsInterop; + }; + 0E252FBA5043E82AE7E96DA6EB172D5A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 148469CADF8690152BAB10A58272A43F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 470FE31978DC918618A329D8B55C85FF; + remoteInfo = Protobuf; + }; + 1A12587DD794CA9955F23A75370F8EAD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7C4F2B07D36F87501AA418B0A2B9B20; + remoteInfo = Swiftilities; + }; + 1BF24697EA008F1406020E754EF90367 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 470FE31978DC918618A329D8B55C85FF; + remoteInfo = Protobuf; + }; + 1F2EFDBE486B46D9BB0ACA670DCE64E5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A3282A5B2437E609EEB85861D7ECE717; + remoteInfo = AppCenter; + }; + 1FDC68635BD8EB1847D7ABA3BDED5D08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D372E53E2E8FEAA06A0439FB85E65767; + remoteInfo = FirebaseAnalyticsInterop; + }; + 2643B7A0DCE050B7ED6CFA33DA0F6891 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 615C831BCE925ED486B225B87E44926D; + remoteInfo = KeychainAccess; + }; + 265B4CB516E1900A62F53357B2801D7D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 470FE31978DC918618A329D8B55C85FF; + remoteInfo = Protobuf; + }; + 2871C78E72BACE3957C7839A26C5C9E2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D; + remoteInfo = Alamofire; + }; + 2A7CCB51109B88316A5FC993FB897CEB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + 2E46EEE58DA8EA73341280992D1C5D13 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0E41540D6862472ED7F2FA11669BE1F; + remoteInfo = Crashlytics; + }; + 2E884F9A0CD78CCADB89B607F8BDB639 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C48FB7D363771FBD71AB44C090CB586; + remoteInfo = BonMot; + }; + 3103E425B0EDFA9736C768A7D3E015B9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A983A2D06C5B6AA3D6ABA5CCC0A16725; + remoteInfo = OHHTTPStubs; + }; + 33807B5A769F0C36650DF5EE9C76AB54 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D8229B0397AE8C2F7C11B3F9EFC9362; + remoteInfo = Sourcery; + }; + 39C2E1ACB757D961A3B5FA5055DBDB7A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + 3DB056970030F95365323DB7D483F0E4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = ABB048B191245233986A7CD75FE412A5; + remoteInfo = Fabric; + }; + 43F7D12D0CBAC174D94F813DCDD5FCB4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7C4F2B07D36F87501AA418B0A2B9B20; + remoteInfo = Swiftilities; + }; + 47C1327AD0E022A8CAD8A8A249109E10 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D; + remoteInfo = Alamofire; + }; + 4809F369638E77D13FBA5FDDC4B279F0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + 4C0638D0D195A9000851F687C36E3AF2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 4C4B6E49A1CB5F547EF7EDA8A2894B2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D8229B0397AE8C2F7C11B3F9EFC9362; + remoteInfo = Sourcery; + }; + 5377C294E50C7447C27E7C2D9D0BC8C4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0E41540D6862472ED7F2FA11669BE1F; + remoteInfo = Crashlytics; + }; + 543BCBF2DF409AB1D8FBE0BB138681A9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 5576D78AFE2208B1EEFB5282D84D1F08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = ABB048B191245233986A7CD75FE412A5; + remoteInfo = Fabric; + }; + 5802AA2B78C7A3E6CF58C77D762D71E9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B593490A33943610DC035C394E10D07A; + remoteInfo = Instabug; + }; + 5B756F4043C0BF271158008CDED79D84 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4607A9D579EE69C57F52971930107170; + remoteInfo = Anchorage; + }; + 61CD1DC5DB1618415917A6B6B148544A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C48FB7D363771FBD71AB44C090CB586; + remoteInfo = BonMot; + }; + 635675962B01177CB052EE57060E9175 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 650053CB0020B8878A2D404A11BA8849 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + 66BF61E910A9B80A8316776974C2BB95 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 689919C1E5546B4C5075358DC52F3565 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5895B432FE4D2F6826C8FF25A09DB6D2; + remoteInfo = FirebaseMessaging; + }; + 689D82AE9C6AAEF561CBC45F0C3F37D8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 6ECBB905773B62DD8276A7843DE12298 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 73FE5A0BD5D3991167C7C54DD4D446DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 75EA1E73941199F90021A0EBD5ED4264 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 79EEB88422FF194A2426408E288FCAA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4607A9D579EE69C57F52971930107170; + remoteInfo = Anchorage; + }; + 7A591D0D32FC2DC7C5953B14551C8425 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 92AABBA7207468A376E84C3CAB584DF1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7C4F2B07D36F87501AA418B0A2B9B20; + remoteInfo = Swiftilities; + }; + 93FC40FACD2A3CAE5B749D36454B21BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 95B892EE3C9D4BCC89AA02E77558C5CF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1E798429DCFA7906F6625CCFC1088744; + remoteInfo = SwiftGen; + }; + 9DE5315A218DF3035FAB4B2C9C4D11CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D8229B0397AE8C2F7C11B3F9EFC9362; + remoteInfo = Sourcery; + }; + A0D8BA7AAAA886E42762C6361B9E93C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + A57D1B3D3A7F6453569CBAD3F3B57B2B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + B269AA35A62F09500537A4BA3BFB44C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 615C831BCE925ED486B225B87E44926D; + remoteInfo = KeychainAccess; + }; + B5EC11065BDE7CEAB67D207F576271FB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D; + remoteInfo = Alamofire; + }; + BA9CC50F725C6CC259A91562DDF28E28 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + BAE33B3D752C070CD5F2887D4F50B516 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + BBA3C65F4427758819F8FE0EB02A684A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1E798429DCFA7906F6625CCFC1088744; + remoteInfo = SwiftGen; + }; + BE218348DB050D18EB6D52F098627920 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; + remoteInfo = SwiftLint; + }; + BF2E36C9AB9868362ECE4F7D15CA684C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = ABB048B191245233986A7CD75FE412A5; + remoteInfo = Fabric; + }; + C6B51788BF5B5F1CA75F34172EAC8C66 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + C80C2AF874999BC32CD68D52CF8B6442 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4607A9D579EE69C57F52971930107170; + remoteInfo = Anchorage; + }; + CC51CF93141CEA0C62DE97225C0BC04E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + CCD653DB7DAA28F82561ABBA8580BADE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 95F19093D340358F7EE721EC01F43355; + remoteInfo = SimulatorStatusMagic; + }; + D10A23904F9F6203C441116CC0642596 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + D9CCC0B18E86FDC85771011139ACDCD4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + DB41FC5EB5ED2499B0E89BB46AA4359B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 615C831BCE925ED486B225B87E44926D; + remoteInfo = KeychainAccess; + }; + DCD1C96ECC57BB8FC7BB0C12A709B9F1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; + remoteInfo = SwiftLint; + }; + DEF897143670388E42D9901AD7FECCDC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + DF4A594B4218CCA9EF0D5B89B5EFB551 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A3282A5B2437E609EEB85861D7ECE717; + remoteInfo = AppCenter; + }; + DF66A2F4782D1A0979660E315CF32196 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; + remoteInfo = SwiftLint; + }; + E327328558089D481E112C8A4A506DE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + E50E5C34A42ACE328C4D101E74D0E458 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5895B432FE4D2F6826C8FF25A09DB6D2; + remoteInfo = FirebaseMessaging; + }; + E9C5672F0CD0FA063A46323C4AC136D2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 95F19093D340358F7EE721EC01F43355; + remoteInfo = SimulatorStatusMagic; + }; + F08459BC4BC97915AAF676A70BA1044E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5895B432FE4D2F6826C8FF25A09DB6D2; + remoteInfo = FirebaseMessaging; + }; + F3A392E1ED6D4068A572BD13DC958074 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D372E53E2E8FEAA06A0439FB85E65767; + remoteInfo = FirebaseAnalyticsInterop; + }; + F7B77B6FF52752D1C86E594584C3D247 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + F83820FC705E1ACB652B680E9ED10441 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C48FB7D363771FBD71AB44C090CB586; + remoteInfo = BonMot; + }; + FBBD79508378F74FDD48FDE8FBD95CA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + FC1D9ED47627FC05FEF6B4B3B5CDB53C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FCD9915FE83842AE0201096155515772; + remoteInfo = "AppCenter-AppCenterDistributeResources"; + }; + FCB8621B4850804581799AA75D809CD9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + FE3AF2118BF9BD4601F3A147DBC26D4C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B593490A33943610DC035C394E10D07A; + remoteInfo = Instabug; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0055556FD5940D94B5719D2CE306ED83 /* BonMot-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BonMot-dummy.m"; sourceTree = ""; }; + 00D5703DE6D32E8BEE77AC1C2A64D12F /* OHHTTPStubsSwift.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OHHTTPStubsSwift.swift; path = OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift; sourceTree = ""; }; + 0124BA8F81579A732104EE20E5A04876 /* AppCenterDistribute.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenterDistribute.framework; path = "AppCenter-SDK-Apple/iOS/AppCenterDistribute.framework"; sourceTree = ""; }; + 01502087710687B101E4DBC35B149B69 /* NavTitleTransitionBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NavTitleTransitionBehavior.swift; path = "Pod/Classes/Lifecycle/Behaviors/Nav-Bar-Title-Transition/NavTitleTransitionBehavior.swift"; sourceTree = ""; }; + 016ABA6E4EC051693A5A08A27FAAA7DC /* Swiftilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Swiftilities-dummy.m"; sourceTree = ""; }; + 0172526E6D3CEFD172AD72474B7F1B03 /* pt.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pt.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pt.lproj"; sourceTree = ""; }; + 01CDC0351ED7CEC107FB8A77489F99CE /* Alamofire-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alamofire-dummy.m"; sourceTree = ""; }; + 01FC0E2DFCCF55217572DC39EA5C6163 /* GPBMessage_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBMessage_PackagePrivate.h; path = objectivec/GPBMessage_PackagePrivate.h; sourceTree = ""; }; + 0245E1DD96C5A71E0976E257585FB875 /* FIRAppAssociationRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAppAssociationRegistration.m; path = Firebase/Core/FIRAppAssociationRegistration.m; sourceTree = ""; }; + 029DC932573FD3CFF2AB08725C770343 /* Pods_Services.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Services.framework; path = "Pods-Services.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 031FC7BA2605BE0368D9692DBDC15D81 /* Anchorage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Anchorage-umbrella.h"; sourceTree = ""; }; + 046CA33B599DC985AC83516113232E99 /* FIRInstanceIDAPNSInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAPNSInfo.h; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.h; sourceTree = ""; }; + 047E636E2BACE2765A28ADD8F0A0E5CA /* SDStatusBarOverriderPost9_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost9_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost9_0.m; sourceTree = ""; }; + 053874D026363AC0A03A09A01558AD61 /* GPBWireFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBWireFormat.h; path = objectivec/GPBWireFormat.h; sourceTree = ""; }; + 05E39D129D919E418F8D526AC9591021 /* Type.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = objectivec/google/protobuf/Type.pbobjc.h; sourceTree = ""; }; + 0613D7FC4E5B1B63B0C08F9883F7B6CB /* Timeline.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Timeline.swift; path = Source/Timeline.swift; sourceTree = ""; }; + 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.xcconfig; sourceTree = ""; }; + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = nanopb.framework; path = nanopb.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 075A60A7C92F557056B739FD7E6BD32C /* AccessibilityHelpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityHelpers.swift; path = Pod/Classes/AccessibilityHelpers/AccessibilityHelpers.swift; sourceTree = ""; }; + 08DA9B3BA661AA7124AE37AFA1396048 /* FIRInstanceIDTokenOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.m; sourceTree = ""; }; + 0904254547F200171C92FAE60BF75E4B /* FIRInstanceIDCheckinStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinStore.m; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.m; sourceTree = ""; }; + 0951EED81BCFA0803E2B141DE332E11D /* FIRMessagingConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingConnection.h; path = Firebase/Messaging/FIRMessagingConnection.h; sourceTree = ""; }; + 0AD7A8A7135C2FC81974892005E66656 /* Response.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Response.swift; path = Source/Response.swift; sourceTree = ""; }; + 0B179EF2E474E501FD5650C4ADF83782 /* GPBMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBMessage.h; path = objectivec/GPBMessage.h; sourceTree = ""; }; + 0B7FB0654F18D64FE0D7A2EAAC682B23 /* UIView+Instabug.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+Instabug.h"; path = "Instabug.framework/Headers/UIView+Instabug.h"; sourceTree = ""; }; + 0B8FDDE48F44189CC0D2FC2CAA0D5C49 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = iOS/Crashlytics.framework; sourceTree = ""; }; + 0D5C9E49FD0B96CC5F0A774F637668F2 /* FirebaseInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstanceID.h; path = Firebase/InstanceID/Public/FirebaseInstanceID.h; sourceTree = ""; }; + 0D70F6C27F2262A020CDFA6DBA6E0A95 /* ViewControllerLifecycleBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ViewControllerLifecycleBehavior.swift; path = Pod/Classes/Lifecycle/Framework/ViewControllerLifecycleBehavior.swift; sourceTree = ""; }; + 0D7113D1B1F68315334A5D6E5C78151A /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDictionary_PackagePrivate.h; path = objectivec/GPBDictionary_PackagePrivate.h; sourceTree = ""; }; + 0D8C01D7DC37A7E86CB6EB912842D669 /* GULLoggerCodes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerCodes.h; path = GoogleUtilities/Common/GULLoggerCodes.h; sourceTree = ""; }; + 0E1E27256DFC0F8898600F8DA01A1D3E /* FIRInstanceIDURLQueryItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDURLQueryItem.h; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.h; sourceTree = ""; }; + 0ED0360339FFD929C312164430AECEF5 /* Protocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Protocols.swift; path = Pod/Classes/Views/Textview/Protocols.swift; sourceTree = ""; }; + 0F5EF93A5BE453909C31B9C6554C95CD /* ja.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ja.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ja.lproj"; sourceTree = ""; }; + 0FF31F44B7641D6494DCF4BD9B15D1D2 /* Instabug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Instabug.framework; sourceTree = ""; }; + 1064EA2176F4289B3F2DC02849A83825 /* GPBCodedOutputStream_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedOutputStream_PackagePrivate.h; path = objectivec/GPBCodedOutputStream_PackagePrivate.h; sourceTree = ""; }; + 106E91C219A27E966E2F6168D1D7F3CA /* FIRConfigurationInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfigurationInternal.h; path = Firebase/Core/Private/FIRConfigurationInternal.h; sourceTree = ""; }; + 10D13A0F900275F0E08660D22CBD3BD7 /* FIRInstanceID+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceID+Private.h"; path = "Firebase/InstanceID/FIRInstanceID+Private.h"; sourceTree = ""; }; + 11AF731E4071DCD5E34B4CA294302B92 /* AppCenterDistributeResources.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = AppCenterDistributeResources.bundle; path = "AppCenter-AppCenterDistributeResources.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + 11EF24F4E2A79E63296F2034D972DD0A /* FIRInstanceIDConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDConstants.h; path = Firebase/InstanceID/FIRInstanceIDConstants.h; sourceTree = ""; }; + 1248BFF6EDD2B0B1963D8E18335E0DCD /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Source/SessionDelegate.swift; sourceTree = ""; }; + 12D36157D372B866FB49CE4288D881E3 /* GtalkCore.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GtalkCore.pbobjc.h; path = Firebase/Messaging/Protos/GtalkCore.pbobjc.h; sourceTree = ""; }; + 1358F7B95EC32C0D0017CE9DBF481067 /* Pods-Services.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.develop.xcconfig"; sourceTree = ""; }; + 137550D164A3DC3110CE137D5BC383BE /* FIRApp.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRApp.m; path = Firebase/Core/FIRApp.m; sourceTree = ""; }; + 13811593551EEF5606EAEAC864156243 /* FIRInstanceIDKeyPairStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeyPairStore.m; path = Firebase/InstanceID/FIRInstanceIDKeyPairStore.m; sourceTree = ""; }; + 13EF5B0944ABC90005395BF63E59D1B9 /* SDStatusBarOverriderPost9_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost9_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost9_0.h; sourceTree = ""; }; + 13FC2F155F0438B5C95978061F39743F /* Anchorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Anchorage.swift; path = Source/Anchorage.swift; sourceTree = ""; }; + 14E3AE25C553C268ECABA7BA60383152 /* GULReachabilityChecker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityChecker.h; path = GoogleUtilities/Reachability/Private/GULReachabilityChecker.h; sourceTree = ""; }; + 1500A31AAD61B6B55D1541CEC1F8B821 /* FIRMessagingLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingLogger.m; path = Firebase/Messaging/FIRMessagingLogger.m; sourceTree = ""; }; + 1546A7379CB47F23D0B23E42B46F302D /* Swiftilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Swiftilities.modulemap; sourceTree = ""; }; + 15A36FCCB6649BA511408B3F1D946285 /* BonMot-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BonMot-Info.plist"; sourceTree = ""; }; + 15D1AB7F35E8D9D69E2A3E30D0AFA1F1 /* GULLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLogger.h; path = GoogleUtilities/Logger/Private/GULLogger.h; sourceTree = ""; }; + 1683A78B7B9007625AE95AAE42A96663 /* ko.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ko.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ko.lproj"; sourceTree = ""; }; + 168D0C5421335ACFB5EBB53C584D8B5D /* GPBDescriptor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDescriptor.h; path = objectivec/GPBDescriptor.h; sourceTree = ""; }; + 16C9E7ABD2EF227BB7684A8307667F72 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist"; sourceTree = ""; }; + 179351A254DB884FEB79BA11A69753BF /* IBGTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGTypes.h; path = Instabug.framework/Headers/IBGTypes.h; sourceTree = ""; }; + 17E33041B314FA837A3CAEB9DF3CDE9F /* OHHTTPStubs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = OHHTTPStubs.framework; path = OHHTTPStubs.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 180977BDD0E3E3ED4CC91DF5BCD29868 /* SDStatusBarOverriderPost8_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost8_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost8_3.m; sourceTree = ""; }; + 186880608DAD6477417FCC20081E68DF /* FIRInstanceIDCheckinPreferences+Internal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceIDCheckinPreferences+Internal.m"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m"; sourceTree = ""; }; + 18DE3A66023F031C118C9FA1671ACC93 /* FIRInstanceID+Private.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceID+Private.m"; path = "Firebase/InstanceID/FIRInstanceID+Private.m"; sourceTree = ""; }; + 1987EE9FAD1DBEC74F2716EA5DC6B2D0 /* Pods-Services.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.appstore.xcconfig"; sourceTree = ""; }; + 1997495D70A0AFDD3D4437EFFABE3048 /* SDStatusBarOverriderPost10_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost10_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost10_3.h; sourceTree = ""; }; + 1A2C2A90AABD3780C5969C4B208AF34F /* FIRAnalyticsConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsConfiguration.h; path = Firebase/Core/Private/FIRAnalyticsConfiguration.h; sourceTree = ""; }; + 1B6C4D3F28F3CBA7CF305CB592F85E32 /* IBGCrashReporting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGCrashReporting.h; path = Instabug.framework/Headers/IBGCrashReporting.h; sourceTree = ""; }; + 1B77C6FBEB46883FCDBBBF0333AAA959 /* LicenseFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LicenseFormatter.swift; path = Pod/Classes/LicenseFormatter/LicenseFormatter.swift; sourceTree = ""; }; + 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Instabug.xcconfig; sourceTree = ""; }; + 1C37EAC158A77C4D6904556D7810ED89 /* FIRInstanceIDKeyPair.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeyPair.h; path = Firebase/InstanceID/FIRInstanceIDKeyPair.h; sourceTree = ""; }; + 1D68553FA13FBC980DEA48AD8F4FF33C /* Protobuf-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Protobuf-Info.plist"; sourceTree = ""; }; + 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SimulatorStatusMagic.xcconfig; sourceTree = ""; }; + 1E28DADD6AFEF6A2BABCAA95C90585AE /* FIRInstanceIDCheckinPreferences_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences_Private.h; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h; sourceTree = ""; }; + 1F13E67C41FD3508A00AC0A6F6CA8A43 /* FIRMessagingRmq2PersistentStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRmq2PersistentStore.m; path = Firebase/Messaging/FIRMessagingRmq2PersistentStore.m; sourceTree = ""; }; + 1F16A3F715737A448BD6736FC7CE8C23 /* FirebaseMessaging-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseMessaging-dummy.m"; sourceTree = ""; }; + 1F6EBA7C6997FF0B01735341A694592F /* Type.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = objectivec/google/protobuf/Type.pbobjc.m; sourceTree = ""; }; + 1F937168226D3E9CD0FDFCA1B32629DA /* SDStatusBarOverriderPre8_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPre8_3.h; path = SDStatusBarManager/SDStatusBarOverriderPre8_3.h; sourceTree = ""; }; + 1FC6D095DAD42D44CCD8E75BCB2FE43F /* Pods-Services-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Services-acknowledgements.plist"; sourceTree = ""; }; + 20D53BC1D9D046786E39FFC97B7B43A7 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBWellKnownTypes.h; path = objectivec/GPBWellKnownTypes.h; sourceTree = ""; }; + 21518DB69A5249884D47AA1C030D65A1 /* GtalkCore.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GtalkCore.pbobjc.m; path = Firebase/Messaging/Protos/GtalkCore.pbobjc.m; sourceTree = ""; }; + 21921F807B4B34CE95F4333954EF9330 /* SDStatusBarOverriderPost10_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost10_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost10_3.m; sourceTree = ""; }; + 2207F5B391C14F1738C82A01AFB21DD1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 22D1FCC1043B4DD3CEA939877906ECD8 /* Any.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = objectivec/google/protobuf/Any.pbobjc.h; sourceTree = ""; }; + 22D8C3460BFD762A935246A9445DDDB6 /* nanopb-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-umbrella.h"; sourceTree = ""; }; + 233D6E7BF9D19F75FCD75EB9691646DB /* GoogleUtilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-prefix.pch"; sourceTree = ""; }; + 23F5E88F86F777E70C48C646149BA42B /* Transform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transform.swift; path = Sources/Transform.swift; sourceTree = ""; }; + 245165C00B0AB8EFA8DF3D2BBC1F3C8D /* TableSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableSection.swift; path = Pod/Classes/TableViewHelpers/TableSection.swift; sourceTree = ""; }; + 247C04FA03FB22629ED9C337A195F8F6 /* OHHTTPStubsResponse+JSON.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "OHHTTPStubsResponse+JSON.h"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h"; sourceTree = ""; }; + 24FEA1649F859C025807618A170C83B1 /* FIRInstanceIDStringEncoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStringEncoding.h; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.h; sourceTree = ""; }; + 258251CAB54F309E8E640653850C4B32 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBWellKnownTypes.m; path = objectivec/GPBWellKnownTypes.m; sourceTree = ""; }; + 26820BF7BDA3D0A1D104CE81E2CF5EEE /* Notifications.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Notifications.swift; path = Source/Notifications.swift; sourceTree = ""; }; + 26880FF9FEB2270469CDC3F44CFC51BE /* FIRInstanceIDCombinedHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCombinedHandler.m; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.m; sourceTree = ""; }; + 2707310D83A1EE6275AED80C0CF694FE /* ContextualAlternates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContextualAlternates.swift; path = Sources/ContextualAlternates.swift; sourceTree = ""; }; + 2765A7D6EF27B9AB42D6279A14D1669A /* UITextView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITextView+Extensions.swift"; path = "Pod/Classes/Views/Textview/UITextView+Extensions.swift"; sourceTree = ""; }; + 288D811BFAFF4D05B72871868528971C /* NamedStyles.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NamedStyles.swift; path = Sources/NamedStyles.swift; sourceTree = ""; }; + 29977CBD0F0F1352A376A22E58D14F56 /* FIRMessagingInternalUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingInternalUtilities.h; path = Firebase/Messaging/InternalHeaders/FIRMessagingInternalUtilities.h; sourceTree = ""; }; + 2B6941F28C59EA39D79CAAF8560210A4 /* Pods-Services-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Services-acknowledgements.markdown"; sourceTree = ""; }; + 2B76802A61020D8F2FF87DBC22F95501 /* FIRInstanceIDAuthService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthService.h; path = Firebase/InstanceID/FIRInstanceIDAuthService.h; sourceTree = ""; }; + 2C51C1D95A23094AED0ABE47DE23F077 /* FIRMessagingClient.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingClient.h; path = Firebase/Messaging/FIRMessagingClient.h; sourceTree = ""; }; + 2CA2C241BE9B8942C2622A8288159183 /* Internal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Internal.swift; path = Source/Internal.swift; sourceTree = ""; }; + 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.xcconfig; sourceTree = ""; }; + 2D45D29B213853B66B8B282991CCF083 /* GULLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerLevel.h; path = GoogleUtilities/Logger/Public/GULLoggerLevel.h; sourceTree = ""; }; + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstanceID.framework; path = FirebaseInstanceID.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DA62A31E606D66A0A8DF99FFB00CB54 /* ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; sourceTree = ""; }; + 2DE296C57E7600238C8BE1E7BEE31B00 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-acknowledgements.plist"; sourceTree = ""; }; + 2DF285A229D15CB8F3DFBB3DD3DC7884 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownField_PackagePrivate.h; path = objectivec/GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; + 2E5D20BCCFC283EBF43CD654944F92FB /* Any.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = objectivec/google/protobuf/Any.pbobjc.m; sourceTree = ""; }; + 2F6E205211513A677E520BAD5BD8C183 /* AnchorGroupProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnchorGroupProvider.swift; path = Source/AnchorGroupProvider.swift; sourceTree = ""; }; + 2F6F1BBF9B142B5EF49F87D2D044E829 /* OHHTTPStubs-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-umbrella.h"; sourceTree = ""; }; + 2F85F03D3204EDFA79866F18C991616C /* FormattedTextField.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FormattedTextField.swift; path = Pod/Classes/FormattedTextField/FormattedTextField.swift; sourceTree = ""; }; + 2FA78D05699B3A7B758DCA452BE2C72E /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/MessageUI.framework; sourceTree = DEVELOPER_DIR; }; + 2FDE57075083813209769DB1ECBA097C /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = objectivec/google/protobuf/Timestamp.pbobjc.h; sourceTree = ""; }; + 300E24828164112EB400CCFD1E0D55B9 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.debug.xcconfig"; sourceTree = ""; }; + 30C8877C44A2A9CEF55FFA4B756AB34A /* FIRInstanceIDDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDDefines.h; path = Firebase/InstanceID/FIRInstanceIDDefines.h; sourceTree = ""; }; + 318F5854818D012A621F4EE3E8A310B3 /* FIRMessagingClient.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingClient.m; path = Firebase/Messaging/FIRMessagingClient.m; sourceTree = ""; }; + 319AFABD7CD5670EEEE2D2BA15A360BD /* GULLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULLogger.m; path = GoogleUtilities/Logger/GULLogger.m; sourceTree = ""; }; + 31ADA9CE18EE4DD7B2A1D3B81C8C8B97 /* Crashlytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Crashlytics.h; path = iOS/Crashlytics.framework/Headers/Crashlytics.h; sourceTree = ""; }; + 322AE82498430F3AA39C51C2BC4FB15F /* SDStatusBarOverriderPost12_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost12_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost12_0.h; sourceTree = ""; }; + 322D077B4897B4E6A8C083170A121575 /* pb_decode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_decode.h; sourceTree = ""; }; + 32FC646A39309A016A43413CF59D0AB3 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist"; sourceTree = ""; }; + 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.xcconfig; sourceTree = ""; }; + 33A4868B2CB72C28A43C9793FA150418 /* BonMot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = BonMot.framework; path = BonMot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 346C27A97925A47261C4B6AC76983CD3 /* Swiftilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Swiftilities-Info.plist"; sourceTree = ""; }; + 356BEB97A3924CA7A9EFA6E39B529298 /* FIRMessagingPersistentSyncMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPersistentSyncMessage.m; path = Firebase/Messaging/FIRMessagingPersistentSyncMessage.m; sourceTree = ""; }; + 35BA4A04ECE9B5B06B1021FB70BBB8E9 /* Alamofire-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Alamofire-Info.plist"; sourceTree = ""; }; + 35D0212C3DBD3EB9B48F92FE6E705124 /* GULNetworkMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkMessageCode.h; path = GoogleUtilities/Network/Private/GULNetworkMessageCode.h; sourceTree = ""; }; + 360D12ED7F2D4981DBE39DE4FCDC76A3 /* FIRMessagingConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingConstants.h; path = Firebase/Messaging/FIRMessagingConstants.h; sourceTree = ""; }; + 365D0C4EEEA6C8DB030220CF3E73772A /* UIView+KeyboardLayoutGuide.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+KeyboardLayoutGuide.swift"; path = "Pod/Classes/Keyboard/UIView+KeyboardLayoutGuide.swift"; sourceTree = ""; }; + 36624989E8CA8F0B22557AD8E3ACAEEF /* GULUserDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULUserDefaults.m; path = GoogleUtilities/UserDefaults/GULUserDefaults.m; sourceTree = ""; }; + 367EF090BA9D626CCBE6C72374BAB47B /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoding.swift; path = Source/ParameterEncoding.swift; sourceTree = ""; }; + 367F00084F5782810F06E3AE60988239 /* FIRBundleUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRBundleUtil.m; path = Firebase/Core/FIRBundleUtil.m; sourceTree = ""; }; + 3739B5667A1C1B8452C08E5FB55014E5 /* FIRInstanceIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenStore.m; path = Firebase/InstanceID/FIRInstanceIDTokenStore.m; sourceTree = ""; }; + 37D1089A0FB89C55B768CC26C804A7B2 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionRegistry.m; path = objectivec/GPBExtensionRegistry.m; sourceTree = ""; }; + 37E010E6C2F14B116AD0A6E40D547F39 /* FIRMessagingSecureSocket.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingSecureSocket.h; path = Firebase/Messaging/FIRMessagingSecureSocket.h; sourceTree = ""; }; + 38337959621A4D9065BD17ACB25371AD /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = objectivec/google/protobuf/Wrappers.pbobjc.m; sourceTree = ""; }; + 39011BD939C3832DBBFC0228D3EF5804 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-acknowledgements.markdown"; sourceTree = ""; }; + 399A0F9FCF8F163E53341ADFC13A530F /* GPBDescriptor_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDescriptor_PackagePrivate.h; path = objectivec/GPBDescriptor_PackagePrivate.h; sourceTree = ""; }; + 3B333D83F4602F037A199CE1061A7A79 /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = objectivec/google/protobuf/FieldMask.pbobjc.h; sourceTree = ""; }; + 3B5E83DF94AA1871CCE123E6D44F0B70 /* GULMutableDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULMutableDictionary.m; path = GoogleUtilities/Network/GULMutableDictionary.m; sourceTree = ""; }; + 3BA9EA5998AA76F74EE798C3CBBECA9D /* FIRMessagingPacketQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPacketQueue.m; path = Firebase/Messaging/FIRMessagingPacketQueue.m; sourceTree = ""; }; + 3C1809F979F3942E4C48A86D0F20B10B /* FIRMessagingVersionUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingVersionUtilities.m; path = Firebase/Messaging/FIRMessagingVersionUtilities.m; sourceTree = ""; }; + 3C43A20C9129EB73F5BA4F3C40D9A27A /* Pods_{{ cookiecutter.project_name | replace(' ', '') }}.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_{{ cookiecutter.project_name | replace(' ', '') }}.framework; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C9D78BDFE3971F2EF43F1EE93290481 /* OHHTTPStubsResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsResponse.m; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.m; sourceTree = ""; }; + 3CE8A623704EA768F5F5576533B75CC4 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.appstore.xcconfig"; sourceTree = ""; }; + 3CFCAB771CD0ED282F14A09984871047 /* MultipartFormData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartFormData.swift; path = Source/MultipartFormData.swift; sourceTree = ""; }; + 3D6419DC93CAC1E865DD9A730B5C8623 /* AcknowledgementsListViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementsListViewModel.swift; path = Pod/Classes/Acknowledgements/AcknowledgementsListViewModel.swift; sourceTree = ""; }; + 3D6B1D921CE2EF324C684690E9B44CD4 /* AFError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AFError.swift; path = Source/AFError.swift; sourceTree = ""; }; + 3D735903962EFF3FC6A7517312F923CA /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = Firebase/Core/Private/FIRDependency.h; sourceTree = ""; }; + 3E381DBDE829EC743F4F0A730A0EA4E5 /* GULNetworkConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkConstants.m; path = GoogleUtilities/Network/GULNetworkConstants.m; sourceTree = ""; }; + 3F5BB4D560F726BDE1F35DA184B1268B /* TintedButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TintedButton.swift; path = Pod/Classes/TintedButton/TintedButton.swift; sourceTree = ""; }; + 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalyticsInterop.xcconfig; sourceTree = ""; }; + 422359491E6C68A5FEFC4E916C0385EF /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap"; sourceTree = ""; }; + 422661E817D097522D8B376CDBD2FD9C /* SimulatorStatusMagic-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SimulatorStatusMagic-umbrella.h"; sourceTree = ""; }; + 433FD3F0C39CB9CDDF7F51F624242518 /* SDStatusBarOverriderPre8_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPre8_3.m; path = SDStatusBarManager/SDStatusBarOverriderPre8_3.m; sourceTree = ""; }; + 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 43F95FB28B3B3DDC58B3E70C591BD759 /* Pods-Services-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Services-umbrella.h"; sourceTree = ""; }; + 44001909662AEC3C8F8AB4E8044AB034 /* FIRInstanceIDCheckinService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinService.m; path = Firebase/InstanceID/FIRInstanceIDCheckinService.m; sourceTree = ""; }; + 441C8E5411061099355CF78039DCB16A /* NavBarHairlineFadeBehavior.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NavBarHairlineFadeBehavior.swift; path = "Pod/Classes/Lifecycle/Behaviors/Nav-Bar-Hairline-Fade/NavBarHairlineFadeBehavior.swift"; sourceTree = ""; }; + 444803A0ADD399B49C628CFC2947F5D0 /* KeychainAccess-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "KeychainAccess-Info.plist"; sourceTree = ""; }; + 44A66697CB999F1B94BE112FF3F6082E /* FIRMessagingCheckinService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingCheckinService.m; path = Firebase/Messaging/FIRMessagingCheckinService.m; sourceTree = ""; }; + 44CE758ABDDC428058091BE3EF7C9451 /* GoogleUtilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleUtilities-dummy.m"; sourceTree = ""; }; + 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = OHHTTPStubs.xcconfig; sourceTree = ""; }; + 45BCED46E7DDF7FBA46DB0CC8B1E58EB /* FIRInstanceIDURLQueryItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDURLQueryItem.m; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.m; sourceTree = ""; }; + 45D7EE49F14DA03DC27AA4631DE48483 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Source/Result.swift; sourceTree = ""; }; + 45FA4D2E7421B8D456A7B6F36884B54B /* GoogleAppMeasurement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GoogleAppMeasurement.framework; path = Frameworks/GoogleAppMeasurement.framework; sourceTree = ""; }; + 466630EDA0868AA0AB1CEBACE48F76AB /* FIRInstanceIDBackupExcludedPlist.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDBackupExcludedPlist.m; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m; sourceTree = ""; }; + 468332F23F5D358DB2288F3934AEC350 /* FIRMessagingDelayedMessageQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingDelayedMessageQueue.m; path = Firebase/Messaging/FIRMessagingDelayedMessageQueue.m; sourceTree = ""; }; + 4707DEF6F61CF955E8D0164566D43983 /* FIRMessagingVersionUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingVersionUtilities.h; path = Firebase/Messaging/FIRMessagingVersionUtilities.h; sourceTree = ""; }; + 47EBEF062D1954D670444D5FB49CB050 /* GULSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSwizzler.h; path = GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h; sourceTree = ""; }; + 488D7FCF0C4C3011E9931E973C97CB62 /* IBGNetworkLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGNetworkLogger.h; path = Instabug.framework/Headers/IBGNetworkLogger.h; sourceTree = ""; }; + 4A12FC33DD08260C9C378A9C2A227833 /* GPBArray.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBArray.h; path = objectivec/GPBArray.h; sourceTree = ""; }; + 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Anchorage.xcconfig; sourceTree = ""; }; + 4B0940BB70F444E65F6DB52323B97369 /* FIRInstanceIDVersionUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDVersionUtilities.h; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.h; sourceTree = ""; }; + 4B1D3820BB2870B22224C025F97B495A /* GPBDescriptor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBDescriptor.m; path = objectivec/GPBDescriptor.m; sourceTree = ""; }; + 4B4AA562F866C56D8D686538218F79EA /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = Firebase/Core/Private/FIRLibrary.h; sourceTree = ""; }; + 4C3439A40A51D1DD58761BACB9331DD2 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}.develop.xcconfig"; sourceTree = ""; }; + 4D0B98AEB62ED9CED697D20516060929 /* GoogleUtilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleUtilities-Info.plist"; sourceTree = ""; }; + 4D827CD1FACB9020945F3B62976196F5 /* GPBCodedInputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedInputStream.h; path = objectivec/GPBCodedInputStream.h; sourceTree = ""; }; + 4DE6952B80D386C75EA01A7B003A923F /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = objectivec/google/protobuf/Wrappers.pbobjc.h; sourceTree = ""; }; + 4E3D53C87F3183ECB9828E9F2CC13CEF /* AttributedStringTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AttributedStringTransformation.swift; path = Sources/UIKit/AttributedStringTransformation.swift; sourceTree = ""; }; + 4E4A10F6099BBA9290EDF1F50E4E1E06 /* FIRComponentContainerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainerInternal.h; path = Firebase/Core/Private/FIRComponentContainerInternal.h; sourceTree = ""; }; + 4EC0877FA9D2F6B5649644D06256D79A /* Anchorage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Anchorage-prefix.pch"; sourceTree = ""; }; + 4F7DFC7F79DE29AD380D6C23EF374F66 /* TailoredSwiftTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TailoredSwiftTextView.swift; path = Pod/Classes/Views/Textview/TailoredSwiftTextView.swift; sourceTree = ""; }; + 4FC123B26387B1A38B1AAB531554C64E /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = Firebase/Core/Private/FIROptionsInternal.h; sourceTree = ""; }; + 4FC53E880281E6082EF5E821D70B924D /* IBGSurveys.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGSurveys.h; path = Instabug.framework/Headers/IBGSurveys.h; sourceTree = ""; }; + 4FCB1518EBBFFD314F997C63F2AE720F /* Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Compatibility.h; path = OHHTTPStubs/Sources/Compatibility.h; sourceTree = ""; }; + 5079F288993DCE2E3F57BD1ECD985F0E /* BonMot-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BonMot-prefix.pch"; sourceTree = ""; }; + 5099DC3344B97A39551F2FD82C61B62E /* FirebaseMessaging-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseMessaging-Info.plist"; sourceTree = ""; }; + 5112CE97A821E9C641D75D1ADAC3EB32 /* TextAlignmentConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextAlignmentConstraint.swift; path = Sources/UIKit/TextAlignmentConstraint.swift; sourceTree = ""; }; + 511A6AAEF7B2FA3135202FCC07BF3E65 /* FIRAnalyticsInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsInterop.h; path = Interop/Analytics/Public/FIRAnalyticsInterop.h; sourceTree = ""; }; + 518BACD57DCD1AA45BE9270B8C5CF1B5 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}.sprint.xcconfig"; sourceTree = ""; }; + 5215C876BC30D194764B41B21031B21F /* FIRInstanceIDCheckinService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinService.h; path = Firebase/InstanceID/FIRInstanceIDCheckinService.h; sourceTree = ""; }; + 526F1F36C6164054C3753D3E4D5C5C6B /* Clamping.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Clamping.swift; path = Pod/Classes/Math/Clamping.swift; sourceTree = ""; }; + 52C88D2EB51952A1D85A0AB4AD8FE1D6 /* Compatibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatibility.swift; path = Sources/Compatibility.swift; sourceTree = ""; }; + 536F55571CB5D4E8C4CD313EFFC98897 /* GPBCodedInputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBCodedInputStream.m; path = objectivec/GPBCodedInputStream.m; sourceTree = ""; }; + 53F88E4F0E3A11E9B5D721DEEDEB2F09 /* SDStatusBarOverriderPost8_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost8_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost8_3.h; sourceTree = ""; }; + 5439C399E40C811A0CC58CD80BF419DB /* GULAppEnvironmentUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppEnvironmentUtil.h; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h; sourceTree = ""; }; + 547CDF4449B3AF5D1990F54FD639448E /* UIKit+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIKit+Helpers.swift"; path = "Sources/UIKit/UIKit+Helpers.swift"; sourceTree = ""; }; + 548F85D6FB2D9B296B3CB2FD0B313CDC /* TaskDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskDelegate.swift; path = Source/TaskDelegate.swift; sourceTree = ""; }; + 552F3B93D76BA12F543F0275D11FB3F6 /* UITableView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITableView+Extensions.swift"; path = "Pod/Classes/TableViewHelpers/UITableView+Extensions.swift"; sourceTree = ""; }; + 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AppCenter.xcconfig; sourceTree = ""; }; + 55C1593407CAC28F4349FBA65B0C1BD9 /* FIRInstanceIDTokenInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenInfo.m; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.m; sourceTree = ""; }; + 55D73A9343E88A26AE65A4223D8C07DF /* Alamofire-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-umbrella.h"; sourceTree = ""; }; + 5674AE212A0219BB0B7D3C5798B9D7E6 /* Answers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Answers.h; path = iOS/Crashlytics.framework/Headers/Answers.h; sourceTree = ""; }; + 569222352AED8AA275E1295F319C179D /* Anchorage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Anchorage-dummy.m"; sourceTree = ""; }; + 56C526BDE19AC726B077CA91F4A3D248 /* FIRInstanceIDKeyPair.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeyPair.m; path = Firebase/InstanceID/FIRInstanceIDKeyPair.m; sourceTree = ""; }; + 571718858875E6D21B448DAAA8A43D00 /* FIRInstanceIDTokenOperation+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDTokenOperation+Private.h"; path = "Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h"; sourceTree = ""; }; + 5725B7F7891756CBC38A7C3FFBA0605D /* FIRMessagingRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRegistrar.h; path = Firebase/Messaging/FIRMessagingRegistrar.h; sourceTree = ""; }; + 5805433E9EE4075EBAE342A288525AD4 /* Duration.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = objectivec/google/protobuf/Duration.pbobjc.h; sourceTree = ""; }; + 58BC5AB95FAF621615835A4436B69D8C /* GPBUnknownField.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownField.h; path = objectivec/GPBUnknownField.h; sourceTree = ""; }; + 598E11382120CC7243651B55798ADF64 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-frameworks.sh"; sourceTree = ""; }; + 59995D0C9E351E7C567DF118C940304B /* PlaceholderTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PlaceholderTextView.swift; path = Pod/Classes/Views/Textview/PlaceholderTextView.swift; sourceTree = ""; }; + 5A3F12E1757587C015AB1F285348CFAB /* OHHTTPStubsResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsResponse.h; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.h; sourceTree = ""; }; + 5AC714289EA97E67199CA997655EAF27 /* FIRInstanceIDTokenInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenInfo.h; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.h; sourceTree = ""; }; + 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.xcconfig; sourceTree = ""; }; + 5B654B4B042BA7DC93766943A643E42B /* FirebaseMessaging.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseMessaging.framework; path = FirebaseMessaging.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5BA55509BAF2F35EE0DDC61B513006A6 /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseCoreDiagnostics.framework; path = Frameworks/FirebaseCoreDiagnostics.framework; sourceTree = ""; }; + 5BD0138F17C5CEC5217CDE58354221B3 /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = objectivec/google/protobuf/SourceContext.pbobjc.h; sourceTree = ""; }; + 5BE4AF9D183DD4AA86ED02D801EC64FA /* nanopb-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "nanopb-Info.plist"; sourceTree = ""; }; + 5C494458D65556B106276B45877C5407 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = Firebase/Core/Private/FIRLogger.h; sourceTree = ""; }; + 5CF43C772DF570A45DC9831438386FF8 /* FIRComponentContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentContainer.m; path = Firebase/Core/FIRComponentContainer.m; sourceTree = ""; }; + 5D1F592A03F29834A482A527C26C43F1 /* LifecycleBehaviorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LifecycleBehaviorViewController.swift; path = Pod/Classes/Lifecycle/Framework/LifecycleBehaviorViewController.swift; sourceTree = ""; }; + 5D2F76C4975A9F75ECFED7459246BDCE /* NSLayoutAnchor+MultiplierConstraints.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutAnchor+MultiplierConstraints.swift"; path = "Source/NSLayoutAnchor+MultiplierConstraints.swift"; sourceTree = ""; }; + 5D6FB40F4F28DA6BC422DDDDBBC7CDA6 /* FirebaseMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseMessaging.h; path = Firebase/Messaging/FirebaseMessaging.h; sourceTree = ""; }; + 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Alamofire.framework; path = Alamofire.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D79D6EFCA519A3D859AD623DEEA3E97 /* Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alamofire.swift; path = Source/Alamofire.swift; sourceTree = ""; }; + 5D93E1401B7CC5204F8F2112E6F2DF1A /* Composable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Composable.swift; path = Sources/Composable.swift; sourceTree = ""; }; + 5EB40E5CF6D5BE4269E687E374531BA9 /* IBGChats.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGChats.h; path = Instabug.framework/Headers/IBGChats.h; sourceTree = ""; }; + 5F619742AF64CEB785C8717E281D3DA7 /* NSError+FIRMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+FIRMessaging.h"; path = "Firebase/Messaging/NSError+FIRMessaging.h"; sourceTree = ""; }; + 5F9E4B9D5FF21ED1F4AB75BA5BA13598 /* FIRMessagingPacketQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPacketQueue.h; path = Firebase/Messaging/FIRMessagingPacketQueue.h; sourceTree = ""; }; + 5FBA28A120B7A31F4D7E17E23F881916 /* FIRAnalyticsConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAnalyticsConfiguration.m; path = Firebase/Core/FIRAnalyticsConfiguration.m; sourceTree = ""; }; + 5FD4F06E7B97586342DC5F130C93CAD6 /* FIRInstanceIDTokenFetchOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenFetchOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h; sourceTree = ""; }; + 60057B688B56F5C62D15997BB9EDEFDD /* GULAppDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h; sourceTree = ""; }; + 6010A7276EC10495D966DCFE5E3C113E /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; }; + 6228C304CE54B8A03AEF3954707FB619 /* FeedbackPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FeedbackPresenter.swift; path = Pod/Classes/AboutView/FeedbackPresenter.swift; sourceTree = ""; }; + 623AE596A3622CB246F0C91BF962A5EA /* FIRMessagingTopicsCommon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingTopicsCommon.h; path = Firebase/Messaging/FIRMessagingTopicsCommon.h; sourceTree = ""; }; + 62F4647B8C0D1352B1C58A2CCAC8F8A1 /* ServerTrustPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServerTrustPolicy.swift; path = Source/ServerTrustPolicy.swift; sourceTree = ""; }; + 63202DA0FE6824272136B2EC50F9FB63 /* Pods-Services.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.debug.xcconfig"; sourceTree = ""; }; + 63782DD22D80D12F0478617EBF8A6E9E /* pb_common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_common.h; sourceTree = ""; }; + 6407CC37ECE767179AE4ED00301D5C52 /* GULOriginalIMPConvenienceMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULOriginalIMPConvenienceMacros.h; path = GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h; sourceTree = ""; }; + 65DFDCD7CA8EB72916D84A809A50C7FD /* SDStatusBarManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarManager.m; path = SDStatusBarManager/SDStatusBarManager.m; sourceTree = ""; }; + 6605561032963C6225A616C84441A72F /* IndexPath+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "IndexPath+Extensions.swift"; path = "Pod/Classes/TableViewHelpers/IndexPath+Extensions.swift"; sourceTree = ""; }; + 661D315940B1DDA7A83242BBBB7CFCA3 /* FIRInstanceIDTokenManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenManager.m; path = Firebase/InstanceID/FIRInstanceIDTokenManager.m; sourceTree = ""; }; + 662B607559C369907018526CD34E7A82 /* FIRMessagingPendingTopicsList.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPendingTopicsList.h; path = Firebase/Messaging/FIRMessagingPendingTopicsList.h; sourceTree = ""; }; + 670326828280195E95A7805733428555 /* GPBBootstrap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBBootstrap.h; path = objectivec/GPBBootstrap.h; sourceTree = ""; }; + 677C759A60BA1A68EC54588ED16024FD /* FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID.h; path = Firebase/InstanceID/Public/FIRInstanceID.h; sourceTree = ""; }; + 67D20FEE4726CCB26A931435C6F7F8D6 /* FIRMessagingSecureSocket.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingSecureSocket.m; path = Firebase/Messaging/FIRMessagingSecureSocket.m; sourceTree = ""; }; + 67E6336A4DE03D2B54BB4E2D5C377405 /* FIRMessagingConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingConstants.m; path = Firebase/Messaging/FIRMessagingConstants.m; sourceTree = ""; }; + 6B4A56D8EB5978D426BDC59DC1AA5E2C /* FIRMessagingContextManagerService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingContextManagerService.h; path = Firebase/Messaging/FIRMessagingContextManagerService.h; sourceTree = ""; }; + 6C651771BDA251122C0517F98DD229C4 /* FIRMessagingContextManagerService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingContextManagerService.m; path = Firebase/Messaging/FIRMessagingContextManagerService.m; sourceTree = ""; }; + 6CF234F15578D78CE0B9F963AE67AD0A /* CLSReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSReport.h; path = iOS/Crashlytics.framework/Headers/CLSReport.h; sourceTree = ""; }; + 6CFEFDB61382511167CBE5BFA016DFF7 /* FIRMessagingExtensionHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingExtensionHelper.m; path = Firebase/Messaging/FIRMessagingExtensionHelper.m; sourceTree = ""; }; + 6D0CAF61CDA366988A208A7B3648AB10 /* FIRMessagingTopicOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingTopicOperation.m; path = Firebase/Messaging/FIRMessagingTopicOperation.m; sourceTree = ""; }; + 6DF740D3ACE024C9F6487F0DBFBBC4B7 /* GULAppDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppDelegateSwizzler.m; path = GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m; sourceTree = ""; }; + 6E2CFBCCEE9CCE0907B805548198E2D4 /* StringStyle+Part.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "StringStyle+Part.swift"; path = "Sources/StringStyle+Part.swift"; sourceTree = ""; }; + 6EB8515E357A8EA23661EBCD579561C3 /* NSError+FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+FIRInstanceID.m"; path = "Firebase/InstanceID/NSError+FIRInstanceID.m"; sourceTree = ""; }; + 6EBEFE4F4DF5F7C86F8F3F2C30FC2380 /* SimulatorStatusMagic-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SimulatorStatusMagic-dummy.m"; sourceTree = ""; }; + 6F446B65463479D1A1BC7E615FB1DB21 /* AboutView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AboutView.swift; path = Pod/Classes/AboutView/AboutView.swift; sourceTree = ""; }; + 6F5FE5A0393B7EA11DA9DBF03DDF5479 /* FIRInstanceIDTokenOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.h; sourceTree = ""; }; + 6FF4D0CB4786B5D9882E4D069869A3CF /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBProtocolBuffers_RuntimeSupport.h; path = objectivec/GPBProtocolBuffers_RuntimeSupport.h; sourceTree = ""; }; + 71A5AB122315590AD0A59A0DA56F3DA9 /* IBGLog.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGLog.h; path = Instabug.framework/Headers/IBGLog.h; sourceTree = ""; }; + 71D265F83D526F8D4CBAF591F57A1C35 /* GULNetwork.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetwork.h; path = GoogleUtilities/Network/Private/GULNetwork.h; sourceTree = ""; }; + 7240263E6AB16234AD51BABC7BEDBFD0 /* FIRMessagingRemoteNotificationsProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRemoteNotificationsProxy.h; path = Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h; sourceTree = ""; }; + 72AA8EF20A9E0ED207B17A82A67948D7 /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = Firebase/Core/Private/FIRComponentContainer.h; sourceTree = ""; }; + 72C7D6029AC9F37ABD0F2A4F076D6125 /* FirebaseInstanceID-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstanceID-Info.plist"; sourceTree = ""; }; + 73047CD3A9D6F102084B6565479FD975 /* OHHTTPStubsResponse+JSON.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubsResponse+JSON.m"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.m"; sourceTree = ""; }; + 73B6B0B82C4B090FD5CCE3E4B3185607 /* GULReachabilityMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityMessageCode.h; path = GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h; sourceTree = ""; }; + 73D447A7F190F1E1C93B83CA52F803B4 /* Pods-Services-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Services-Info.plist"; sourceTree = ""; }; + 741B01C4F4159696D4237F6F4D3A98BB /* OHHTTPStubs-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-prefix.pch"; sourceTree = ""; }; + 74BE747D93A2FF0D9596DFEB89B88506 /* cs.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = cs.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/cs.lproj"; sourceTree = ""; }; + 7558233F38BB01572FA6F6C87087DE05 /* Keyboard.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Keyboard.swift; path = Pod/Classes/Keyboard/Keyboard.swift; sourceTree = ""; }; + 7579D1AD4020ED9620DFC5844850FF1E /* SimulatorStatusMagic-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SimulatorStatusMagic-prefix.pch"; sourceTree = ""; }; + 76848D31B6A54F9167B3E81B2B157273 /* SDStatusBarOverriderPost10_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost10_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost10_0.h; sourceTree = ""; }; + 772EBD4355380FAEEEE486F50277CA1F /* FIRVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVersion.m; path = Firebase/Core/FIRVersion.m; sourceTree = ""; }; + 773F43FA50FABF1CE0C562282F32D624 /* DispatchQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Alamofire.swift"; path = "Source/DispatchQueue+Alamofire.swift"; sourceTree = ""; }; + 7750A59221DB77FAF80CF7B06B985ABA /* FIRMessagingReceiver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingReceiver.m; path = Firebase/Messaging/FIRMessagingReceiver.m; sourceTree = ""; }; + 7798FFAA50C6E5C495F258D8A51AFCF9 /* FIRMessagingPubSub.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPubSub.h; path = Firebase/Messaging/FIRMessagingPubSub.h; sourceTree = ""; }; + 78082F41A23883083EE4061BFC18A4D3 /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = Firebase/Core/Private/FIRErrors.h; sourceTree = ""; }; + 780F31022D4CCCEEEF6B0433A8907F93 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBExtensionInternals.h; path = objectivec/GPBExtensionInternals.h; sourceTree = ""; }; + 781146DAC6F2B33CBAB88F5B7480DA3C /* FIRInstanceIDAuthService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthService.m; path = Firebase/InstanceID/FIRInstanceIDAuthService.m; sourceTree = ""; }; + 781DC562E9BB6624DE3FB5B273AEF265 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-resources.sh"; sourceTree = ""; }; + 78277DF682670FCB6D1E611B6DD72010 /* FIRInstanceIDTokenDeleteOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenDeleteOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h; sourceTree = ""; }; + 784571D4952D4EA67F2018794826B771 /* KeychainAccess.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = KeychainAccess.modulemap; sourceTree = ""; }; + 7852EA1E7C25798259AEA5BCE126639F /* Tracking+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Tracking+Adaptive.swift"; path = "Sources/UIKit/Tracking+Adaptive.swift"; sourceTree = ""; }; + 786594362231C88055784CE1F30F160D /* StringStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StringStyle.swift; path = Sources/StringStyle.swift; sourceTree = ""; }; + 789045C4CD88187B1C8B6952AD65877D /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBProtocolBuffers.h; path = objectivec/GPBProtocolBuffers.h; sourceTree = ""; }; + 7902953F39F914B13DAD07D6C494973D /* FIRLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRLogger.m; path = Firebase/Core/FIRLogger.m; sourceTree = ""; }; + 7930F6E4B1DBA1F8B3A51893DC47D6D9 /* FIRMessagingCheckinService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingCheckinService.h; path = Firebase/Messaging/FIRMessagingCheckinService.h; sourceTree = ""; }; + 793A451BCFED3B0D33EF91ABA0E76DC0 /* MutableCopying.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MutableCopying.swift; path = Sources/MutableCopying.swift; sourceTree = ""; }; + 79B0EA6DE3F64B8EB2ED292B450C2FBB /* Instabug.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Instabug.h; path = Instabug.framework/Headers/Instabug.h; sourceTree = ""; }; + 7A62C867EDE3F5810D57F99ED04E9BA0 /* Struct.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = objectivec/google/protobuf/Struct.pbobjc.h; sourceTree = ""; }; + 7A99BF2E906BA57B9D716EC2F28447CF /* Log.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Log.swift; path = Pod/Classes/Logging/Log.swift; sourceTree = ""; }; + 7B31944D9854B90AB402DAEBC2714BCB /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.sprint.xcconfig"; sourceTree = ""; }; + 7BE9D1869AAADCD42062E01D5D3C87C8 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownFieldSet_PackagePrivate.h; path = objectivec/GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; + 7C5A26153063FDC9CF29CACEBFDCE19B /* GPBUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUtilities.h; path = objectivec/GPBUtilities.h; sourceTree = ""; }; + 7D3E35ACC5108C1B4DEF24DD53900541 /* Keychain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Keychain.swift; path = Lib/KeychainAccess/Keychain.swift; sourceTree = ""; }; + 7D5ABA89BFABB034F15503FA4EA2C665 /* Struct.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = objectivec/google/protobuf/Struct.pbobjc.m; sourceTree = ""; }; + 7DF32B5609DBC1BE477D33A94686964D /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBExtensionRegistry.h; path = objectivec/GPBExtensionRegistry.h; sourceTree = ""; }; + 7DF524EA9012A4ACFCAD0BF6C7247299 /* FIRInstanceIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenStore.h; path = Firebase/InstanceID/FIRInstanceIDTokenStore.h; sourceTree = ""; }; + 7DF716A590C33DA0E5141543D157C552 /* CLSAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSAttributes.h; path = iOS/Crashlytics.framework/Headers/CLSAttributes.h; sourceTree = ""; }; + 7E51F53C43C26EC84AD204A2DF58797C /* NSError+FIRMessaging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+FIRMessaging.m"; path = "Firebase/Messaging/NSError+FIRMessaging.m"; sourceTree = ""; }; + 7E542A623F5A954B3F4D243CF8A4FB46 /* NSError+FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+FIRInstanceID.h"; path = "Firebase/InstanceID/NSError+FIRInstanceID.h"; sourceTree = ""; }; + 7E629EB70356C8FA1AD9781584EA8374 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-dummy.m"; sourceTree = ""; }; + 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BonMot.xcconfig; sourceTree = ""; }; + 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.xcconfig; sourceTree = ""; }; + 7F492B106E8EB1E2C72059F4CEC2ADF4 /* GULAppDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler_Private.h; path = GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h; sourceTree = ""; }; + 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.xcconfig; sourceTree = ""; }; + 7F9F3C7A180A25601F10CA6EDA5435A1 /* Alamofire.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Alamofire.modulemap; sourceTree = ""; }; + 7FF09D8EFD37D437525F039619D3D763 /* GoogleUtilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleUtilities.modulemap; sourceTree = ""; }; + 807724545CC9FBB3B33672198DD057ED /* GULUserDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULUserDefaults.h; path = GoogleUtilities/UserDefaults/Private/GULUserDefaults.h; sourceTree = ""; }; + 809A9FA0958DAAB72D85475C1510B28C /* Api.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = objectivec/google/protobuf/Api.pbobjc.m; sourceTree = ""; }; + 80F2752CD15387DAD8075D0DE08C9A48 /* SimulatorStatusMagic.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SimulatorStatusMagic.modulemap; sourceTree = ""; }; + 814B71C2E085A900096EC6AECF6B4CE3 /* GPBWireFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBWireFormat.m; path = objectivec/GPBWireFormat.m; sourceTree = ""; }; + 82350E48404736EC458CE6073EFD26C3 /* IBGFeatureRequests.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGFeatureRequests.h; path = Instabug.framework/Headers/IBGFeatureRequests.h; sourceTree = ""; }; + 8239448521ADE6944ED02A4E4E8F83C5 /* GULNetworkURLSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkURLSession.h; path = GoogleUtilities/Network/Private/GULNetworkURLSession.h; sourceTree = ""; }; + 829A957DF3BA4C53A538E446773D71B8 /* AppInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppInfo.swift; path = Pod/Classes/AboutView/AppInfo.swift; sourceTree = ""; }; + 829D6EBA77079A9CFF95E76253E1B175 /* fr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fr.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/fr.lproj"; sourceTree = ""; }; + 82C3962E95811D63FBFBD722F2BD0204 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; + 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 842142B2B14A0BA4AFCC17CBAC0F7C98 /* pl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pl.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/pl.lproj"; sourceTree = ""; }; + 846244C0EC47A8A7BE9B1E2506F77C50 /* FIRMessagingRmq2PersistentStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRmq2PersistentStore.h; path = Firebase/Messaging/FIRMessagingRmq2PersistentStore.h; sourceTree = ""; }; + 8466929A49CE3221978EB36183FD35BA /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUtilities_PackagePrivate.h; path = objectivec/GPBUtilities_PackagePrivate.h; sourceTree = ""; }; + 8487A57EC520F91735649B13CF1455E4 /* FIRInstanceIDCheckinPreferences+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDCheckinPreferences+Internal.h"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h"; sourceTree = ""; }; + 849FE1C62D5BADA93D12508A10FFB88A /* FIRMessagingPubSubRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPubSubRegistrar.h; path = Firebase/Messaging/FIRMessagingPubSubRegistrar.h; sourceTree = ""; }; + 84DA61DFF1F0980689DC3F498047D530 /* SimulatorStatusMagic-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SimulatorStatusMagic-Info.plist"; sourceTree = ""; }; + 86773016D7292DB1077AB6ED22B7CAE1 /* Anchorage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Anchorage-Info.plist"; sourceTree = ""; }; + 86B9F61513C3569FB8F5F80587BD0802 /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = Firebase/Core/Private/FIRErrorCode.h; sourceTree = ""; }; + 8750CA9FEFAD9991DCE303273D306351 /* nanopb-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-prefix.pch"; sourceTree = ""; }; + 88B5959D5B7A3E36DDEF6EA561F00502 /* FIRInstanceIDAPNSInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAPNSInfo.m; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.m; sourceTree = ""; }; + 88C8386A2D3A8315518D7FC2CF01A15B /* FIRMessagingTopicOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingTopicOperation.h; path = Firebase/Messaging/FIRMessagingTopicOperation.h; sourceTree = ""; }; + 88F89AA47577A480D576C38E3EDFADAA /* Swiftilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Swiftilities-umbrella.h"; sourceTree = ""; }; + 8942E740881A6372C900E36D68EAF4CB /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBCodedOutputStream.m; path = objectivec/GPBCodedOutputStream.m; sourceTree = ""; }; + 894FB1F3B5CAA20D3A8E5DA58FA415A3 /* OHPathHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHPathHelpers.m; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m; sourceTree = ""; }; + 89A489E0FEA5C5815748A7017DDB2666 /* FirebaseMessaging.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseMessaging.modulemap; sourceTree = ""; }; + 8A10B633A7F6F7DB8565FCD54B2F6015 /* GPBDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBDictionary.m; path = objectivec/GPBDictionary.m; sourceTree = ""; }; + 8A2450A9AC3AEDEE3814CEC1893EBE3F /* Protobuf-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Protobuf-umbrella.h"; sourceTree = ""; }; + 8A467A3E9E3137B15241AA445AAA69D3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; + 8B0B7D7F03E7C5408A9FEDE21398424D /* Pods_{{ cookiecutter.project_name | replace(' ', '') }}_{{ cookiecutter.project_name | replace(' ', '') }}Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_{{ cookiecutter.project_name | replace(' ', '') }}_{{ cookiecutter.project_name | replace(' ', '') }}Tests.framework; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8B4A5B8EBEA544128E7C93E89A933ACE /* GPBRootObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBRootObject.m; path = objectivec/GPBRootObject.m; sourceTree = ""; }; + 8BCBB2D56D50E44BD77F0169A7F75E7B /* FIRMessagingRmqManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingRmqManager.h; path = Firebase/Messaging/FIRMessagingRmqManager.h; sourceTree = ""; }; + 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sourcery.xcconfig; sourceTree = ""; }; + 8C4EB1163B98FFAB7C42AB21C3ACF776 /* Ligatures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Ligatures.swift; path = Sources/Ligatures.swift; sourceTree = ""; }; + 8CC134AECB569C629CF74E270D3E8FC3 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}.debug.xcconfig"; sourceTree = ""; }; + 8E5AF5D638A5E46AC1F536B0D9FC686E /* FIRMessaging_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessaging_Private.h; path = Firebase/Messaging/FIRMessaging_Private.h; sourceTree = ""; }; + 8EA90B335493CD691AF6F92A19615597 /* FIRAnalyticsConnector.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FIRAnalyticsConnector.framework; path = Frameworks/FIRAnalyticsConnector.framework; sourceTree = ""; }; + 8F00E32E42A1E8D5237611B57EB97BFC /* FIRInstanceIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStore.m; path = Firebase/InstanceID/FIRInstanceIDStore.m; sourceTree = ""; }; + 8F4E12C03F40438969454920C49D2013 /* FIRInstanceID_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID_Private.h; path = Firebase/InstanceID/Private/FIRInstanceID_Private.h; sourceTree = ""; }; + 8F63F7236794D312ACB1F32E2BE55CA4 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-umbrella.h"; sourceTree = ""; }; + 8FA9AF149F192E34E86DF398F93B6819 /* Tab.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tab.swift; path = Sources/Tab.swift; sourceTree = ""; }; + 8FD395C6B080D05AA0E9B521C84DE95C /* FirebaseInstanceID-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstanceID-dummy.m"; sourceTree = ""; }; + 900494C92D1BC8DD44B41A1E185446A2 /* FIRComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponent.m; path = Firebase/Core/FIRComponent.m; sourceTree = ""; }; + 91A527A11C0F5C0E19DEF21E7B9C7F7E /* AcknowledgementsListViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementsListViewController.swift; path = Pod/Classes/Acknowledgements/AcknowledgementsListViewController.swift; sourceTree = ""; }; + 9217346EC5CA9E35B7D5CC7A1AC82A9B /* zh-Hans.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hans.lproj"; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hans.lproj"; sourceTree = ""; }; + 9221AE50CB51C7E8CD93A956CC3EA7C2 /* GULNetworkConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkConstants.h; path = GoogleUtilities/Network/Private/GULNetworkConstants.h; sourceTree = ""; }; + 92B3A83AF7CBD24CFB27352A8A473464 /* NSURLRequest+HTTPBodyTesting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSURLRequest+HTTPBodyTesting.h"; path = "OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.h"; sourceTree = ""; }; + 92F4855C80835F853383873CD1CB78B4 /* FIRMessagingRmqManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRmqManager.m; path = Firebase/Messaging/FIRMessagingRmqManager.m; sourceTree = ""; }; + 935548E336DB715970FA91771AE5D568 /* Fabric.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Fabric.h; path = iOS/Fabric.framework/Headers/Fabric.h; sourceTree = ""; }; + 9435CEF7CA7BCE866E215F71262E51F6 /* HairlineView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HairlineView.swift; path = Pod/Classes/HairlineView/HairlineView.swift; sourceTree = ""; }; + 9457CFFC68284D195CF10F91CD0AB794 /* Tab+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Tab+Adaptive.swift"; path = "Sources/UIKit/Tab+Adaptive.swift"; sourceTree = ""; }; + 949C61608ACEFB9BB47A141E428D5CED /* FIRMessagingPubSub.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPubSub.m; path = Firebase/Messaging/FIRMessagingPubSub.m; sourceTree = ""; }; + 94F243E68DA74E3EF1064781840A6375 /* SDStatusBarOverriderPost10_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost10_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost10_0.m; sourceTree = ""; }; + 95728BB595EBF3C2595CF132C9C7AAAC /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-frameworks.sh"; sourceTree = ""; }; + 966E61D7CDD4B8F269B4C52F6C9D4E6F /* GULNSData+zlib.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULNSData+zlib.h"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.h"; sourceTree = ""; }; + 968AD6C6067177F3FFBF4E22B5D62AFA /* Priority.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Priority.swift; path = Source/Priority.swift; sourceTree = ""; }; + 97EFF3947D869F0FC7D7D08A1B3B0A6E /* FIROptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROptions.m; path = Firebase/Core/FIROptions.m; sourceTree = ""; }; + 986EF3488689CACCCB183285A1909D6A /* FIRMessagingCodedInputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingCodedInputStream.m; path = Firebase/Messaging/FIRMessagingCodedInputStream.m; sourceTree = ""; }; + 98DE82806BC35C7A7C3ACBCF0C7B379F /* FIRMessagingAnalytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingAnalytics.h; path = Firebase/Messaging/FIRMessagingAnalytics.h; sourceTree = ""; }; + 990D5BCA382BD9D9D2C3C1E291F2B135 /* FIRComponentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentType.m; path = Firebase/Core/FIRComponentType.m; sourceTree = ""; }; + 9917CC431DC36BB3D118B1AA7A204319 /* es.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = es.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/es.lproj"; sourceTree = ""; }; + 994790A4BDFB35C5FEEEB4B16ACD0073 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = Firebase/Core/Private/FIRComponentType.h; sourceTree = ""; }; + 9A572C6721447ABE0F589A4004BA6EFA /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-dummy.m"; sourceTree = ""; }; + 9A68AA6C83230BBFED7CC97DA09A987B /* FirebaseMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseMessaging.h; path = Firebase/Messaging/Public/FirebaseMessaging.h; sourceTree = ""; }; + 9AAD5AF881A90E6C8ABB964271CD3D7F /* FIRMessagingAnalytics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingAnalytics.m; path = Firebase/Messaging/FIRMessagingAnalytics.m; sourceTree = ""; }; + 9B49BB3E350F98DF8781264F7BB9D61B /* FIRInstanceIDCombinedHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCombinedHandler.h; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.h; sourceTree = ""; }; + 9B7024F62947EF6E2C6FB6CD5B34E2ED /* FIRConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRConfiguration.m; path = Firebase/Core/FIRConfiguration.m; sourceTree = ""; }; + 9BE96B90011674F188BAA0598BD91B53 /* OHHTTPStubs.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubs.m; path = OHHTTPStubs/Sources/OHHTTPStubs.m; sourceTree = ""; }; + 9C8948FFD9D354F2001C98CEE8B45E08 /* FIRMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessaging.h; path = Firebase/Messaging/Public/FIRMessaging.h; sourceTree = ""; }; + 9D4DE2FA59344D4592D75A8D5A4137CE /* UIKit+AdaptableTextContainerSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIKit+AdaptableTextContainerSupport.swift"; path = "Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift"; sourceTree = ""; }; + 9D75377169BF1143EF206F74484FC1F0 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = objectivec/google/protobuf/Timestamp.pbobjc.m; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9E5694DFDF2C9E53E5A1BB537671493B /* Protobuf.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Protobuf.modulemap; sourceTree = ""; }; + 9E603AE6FAEA107641D9E8499AD28ACD /* Special.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Special.swift; path = Sources/Special.swift; sourceTree = ""; }; + 9EE85328C2AA2BE65AC5476B9A3A4B9A /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBRootObject_PackagePrivate.h; path = objectivec/GPBRootObject_PackagePrivate.h; sourceTree = ""; }; + 9EF280833555D9A6C3AB807C1BBEF193 /* FontFeatures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FontFeatures.swift; path = Sources/FontFeatures.swift; sourceTree = ""; }; + 9EF45F089BAE93FE828CD9688AA8CA8A /* KeychainAccess-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KeychainAccess-umbrella.h"; sourceTree = ""; }; + 9F64FB46C163A2D7EEDD531525ED4A3E /* FIRInstanceIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStore.h; path = Firebase/InstanceID/FIRInstanceIDStore.h; sourceTree = ""; }; + A0540CA217C994053589CECC283EFEE1 /* IBGSurvey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGSurvey.h; path = Instabug.framework/Headers/IBGSurvey.h; sourceTree = ""; }; + A1718A38D1F7426976B72AE548700F4E /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-resources.sh"; sourceTree = ""; }; + A23C1F66FE104A9AB25DB49ABA41F52E /* ResponseSerialization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResponseSerialization.swift; path = Source/ResponseSerialization.swift; sourceTree = ""; }; + A39DC1AB08D7C48D33B0213FC070EE91 /* CoreDataStack.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CoreDataStack.swift; path = Pod/Classes/CoreDataStack/CoreDataStack.swift; sourceTree = ""; }; + A3AA81B96ABF2101A80128229B5253C0 /* FIRInstanceIDUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDUtilities.h; path = Firebase/InstanceID/FIRInstanceIDUtilities.h; sourceTree = ""; }; + A45D8D0A1979A555EFB7FFB40FE9E3B3 /* Emphasis.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Emphasis.swift; path = Sources/Emphasis.swift; sourceTree = ""; }; + A48A79CAAFF110C87DF8BF807837AB83 /* FIRInstanceIDConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDConstants.m; path = Firebase/InstanceID/FIRInstanceIDConstants.m; sourceTree = ""; }; + A52569BDA16818151E3735016A95C16B /* UIView+Lookup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+Lookup.swift"; path = "Pod/Classes/Forms/UIView+Lookup.swift"; sourceTree = ""; }; + A64AD290563189B5EC09536986EEA27C /* GoogleUtilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-umbrella.h"; sourceTree = ""; }; + A668229ECF671E377647F4DE649FE2D9 /* GULSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSwizzler.m; path = GoogleUtilities/MethodSwizzler/GULSwizzler.m; sourceTree = ""; }; + A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstanceID.xcconfig; sourceTree = ""; }; + A78104E9B1CB747B9ACC895D21681C1E /* FirebaseCore-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCore-dummy.m"; sourceTree = ""; }; + A787CDE742CEB6FDF5F73F556D790691 /* SimulatorStatusMagic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SimulatorStatusMagic.framework; path = SimulatorStatusMagic.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A86060F6B97532F283FE392A2B356F3F /* FirebaseInstanceID-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstanceID-umbrella.h"; sourceTree = ""; }; + A9F6CAA436B21A9F893735228C041394 /* FIRBundleUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRBundleUtil.h; path = Firebase/Core/Private/FIRBundleUtil.h; sourceTree = ""; }; + AB8C0F48EBA2E62C0D0D696427AAF734 /* tr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = tr.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/tr.lproj"; sourceTree = ""; }; + ABF027D832F3CFAAE988298C13DB25CF /* FIRMessagingPubSubRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPubSubRegistrar.m; path = Firebase/Messaging/FIRMessagingPubSubRegistrar.m; sourceTree = ""; }; + AC024504A5C4B47AE13B434EA483D427 /* FIRErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRErrors.m; path = Firebase/Core/FIRErrors.m; sourceTree = ""; }; + AD145FCE40536EC56F550EF22AE3A2B3 /* GradientView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = Pod/Classes/Views/Gradient/GradientView.swift; sourceTree = ""; }; + AD183A51FD1FF965003291AC5F048C14 /* FIRMessagingConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingConnection.m; path = Firebase/Messaging/FIRMessagingConnection.m; sourceTree = ""; }; + AD4B1920B3B7BA2136B85A1738A0948B /* CLSLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSLogging.h; path = iOS/Crashlytics.framework/Headers/CLSLogging.h; sourceTree = ""; }; + AD72DEE352EC54E08A0DDA10EEDB3D49 /* SDStatusBarOverriderPost11_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost11_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost11_0.m; sourceTree = ""; }; + AD7C3AE346CDF47C559CAA1E29D38819 /* SDStatusBarOverriderPost9_3.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost9_3.m; path = SDStatusBarManager/SDStatusBarOverriderPost9_3.m; sourceTree = ""; }; + AD9FCFD914EDA9CDBDE1BA40686E48E0 /* nanopb-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "nanopb-dummy.m"; sourceTree = ""; }; + ADB4B0347B4897392B2245F4E44D0AC1 /* GPBArray.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBArray.m; path = objectivec/GPBArray.m; sourceTree = ""; }; + ADD85DBCA961517182D229A520E707A7 /* KeychainAccess-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KeychainAccess-prefix.pch"; sourceTree = ""; }; + AF4C07CB531C2A20C075F1E2F27F9807 /* Pods-Services-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Services-dummy.m"; sourceTree = ""; }; + AF915886F12CE018C123DBCE8092ECC5 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-acknowledgements.plist"; sourceTree = ""; }; + AF9BA9F1FCE9E687C9236562D28FBBF6 /* AdaptableTextContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptableTextContainer.swift; path = Sources/UIKit/AdaptableTextContainer.swift; sourceTree = ""; }; + AFE96786D662F36B014DB2976712E52D /* Compatibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatibility.swift; path = Pod/Classes/Compatibility/Compatibility.swift; sourceTree = ""; }; + B02CBEEE2EAAE48F5C59A0748E149382 /* FIRLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLoggerLevel.h; path = Firebase/Core/Public/FIRLoggerLevel.h; sourceTree = ""; }; + B0DF923FAF38D4B7E93295F4F7B7E252 /* OHHTTPStubsMethodSwizzling.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsMethodSwizzling.m; path = OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.m; sourceTree = ""; }; + B1032898B87F1DAFA71E47C7FCB2E415 /* BonMot.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BonMot.modulemap; sourceTree = ""; }; + B11A4E7961F768D0892E18D1649C5FE4 /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkReachabilityManager.swift; path = Source/NetworkReachabilityManager.swift; sourceTree = ""; }; + B1EEA6318B7652582ADC0248EF0E862A /* FIRMessagingDelayedMessageQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingDelayedMessageQueue.h; path = Firebase/Messaging/FIRMessagingDelayedMessageQueue.h; sourceTree = ""; }; + B2127ADF7134D22A7B41243F58B119B2 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBUnknownFieldSet.m; path = objectivec/GPBUnknownFieldSet.m; sourceTree = ""; }; + B2E98DDB0684CD0EED258207851A2A13 /* GULReachabilityChecker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULReachabilityChecker.m; path = GoogleUtilities/Reachability/GULReachabilityChecker.m; sourceTree = ""; }; + B348867894A4CE1D01EE3407670282AA /* FIRInstanceIDLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDLogger.m; path = Firebase/InstanceID/FIRInstanceIDLogger.m; sourceTree = ""; }; + B3B80947892AFE99F690D90E0E6F7A0C /* Empty.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = objectivec/google/protobuf/Empty.pbobjc.h; sourceTree = ""; }; + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleUtilities.framework; path = GoogleUtilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B4625D667AFBD9425C3A79449E05F451 /* FIRMessagingSyncMessageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingSyncMessageManager.m; path = Firebase/Messaging/FIRMessagingSyncMessageManager.m; sourceTree = ""; }; + B477F169CB917A9F07ABB3C6B0ED46BE /* Anchorage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Anchorage.framework; path = Anchorage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B4C8749E960A855A7C7965EC2BA8218A /* GtalkExtensions.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GtalkExtensions.pbobjc.m; path = Firebase/Messaging/Protos/GtalkExtensions.pbobjc.m; sourceTree = ""; }; + B5391DB5CF7FE004619D4F1920521EA2 /* FIRConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfiguration.h; path = Firebase/Core/Public/FIRConfiguration.h; sourceTree = ""; }; + B53967F27884E26D24DE4B390642290C /* Duration.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = objectivec/google/protobuf/Duration.pbobjc.m; sourceTree = ""; }; + B5579787CFCE1BC97D5EF0CCEB731C04 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap"; sourceTree = ""; }; + B5D090276832D4024D8B3A5568BEA4DE /* FIRMessagingReceiver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingReceiver.h; path = Firebase/Messaging/FIRMessagingReceiver.h; sourceTree = ""; }; + B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alamofire.xcconfig; sourceTree = ""; }; + B67FA446F6A78388566D90BDD02B2175 /* FIRMessagingPendingTopicsList.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingPendingTopicsList.m; path = Firebase/Messaging/FIRMessagingPendingTopicsList.m; sourceTree = ""; }; + B7010FC71D49408694A41D0B4A22E831 /* AppCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenter.framework; path = "AppCenter-SDK-Apple/iOS/AppCenter.framework"; sourceTree = ""; }; + B732E75D7C970C6F08CDE5C6AFDF8702 /* zh-Hant.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hant.lproj"; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/zh-Hant.lproj"; sourceTree = ""; }; + B74880F26CD1B4204F6539C5B5502D2E /* EmbeddedTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmbeddedTransformation.swift; path = Sources/UIKit/EmbeddedTransformation.swift; sourceTree = ""; }; + B7873C854D420CA53D1BD7CE0700ACDC /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = objectivec/google/protobuf/FieldMask.pbobjc.m; sourceTree = ""; }; + B7A403AA64C0558925444F207EEADE76 /* OHHTTPStubs-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "OHHTTPStubs-dummy.m"; sourceTree = ""; }; + B7A5E48BA4D6DE7CABBE36B040019834 /* FIRMessagingSyncMessageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingSyncMessageManager.h; path = Firebase/Messaging/FIRMessagingSyncMessageManager.h; sourceTree = ""; }; + B7AD2BE9A6C9E2298E7917BF8FD6E425 /* it.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = it.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/it.lproj"; sourceTree = ""; }; + B7B04D349B7F6EF4AB5D84952D2A53DE /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBUnknownFieldSet.h; path = objectivec/GPBUnknownFieldSet.h; sourceTree = ""; }; + B80D74D41E215EDC00F1A0D8245EC63E /* FIRInstanceIDTokenManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenManager.h; path = Firebase/InstanceID/FIRInstanceIDTokenManager.h; sourceTree = ""; }; + B8D3618FE4C32D4ADBE22D247745AB5F /* FIRInstanceIDBackupExcludedPlist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDBackupExcludedPlist.h; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h; sourceTree = ""; }; + B8E0195AADB4B77EBBA26DCB16A7ADB1 /* FIRMessagingDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingDefines.h; path = Firebase/Messaging/FIRMessagingDefines.h; sourceTree = ""; }; + B8E677CF6BD8B668E00639F75526D6FE /* UIImage+Tinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIImage+Tinting.swift"; path = "Pod/Classes/ImageHelpers/UIImage+Tinting.swift"; sourceTree = ""; }; + B94ED403343770A491208CD276342FF7 /* FIRInstanceIDTokenDeleteOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenDeleteOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m; sourceTree = ""; }; + BA59223CF8122E668F27A492727DA05A /* NSDictionary+FIRMessaging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+FIRMessaging.m"; path = "Firebase/Messaging/NSDictionary+FIRMessaging.m"; sourceTree = ""; }; + BAEE38A7456029D2435589A2AB61BB54 /* FIRInstanceIDLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDLogger.h; path = Firebase/InstanceID/FIRInstanceIDLogger.h; sourceTree = ""; }; + BB5DFE1F01AFD7800F073ECA808AD019 /* GPBRootObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBRootObject.h; path = objectivec/GPBRootObject.h; sourceTree = ""; }; + BBF0EE4B9DF20FB5E0DF535FED448A7E /* pb_decode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_decode.c; sourceTree = ""; }; + BC07246B7DD7857DA18E71CDAD1E01D4 /* FIRMessagingExtensionHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingExtensionHelper.h; path = Firebase/Messaging/Public/FIRMessagingExtensionHelper.h; sourceTree = ""; }; + BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftGen.xcconfig; sourceTree = ""; }; + BCDA99AA3900C0A75CF6AFE7E2BEF2A0 /* UIViewController+Lifecycle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Lifecycle.swift"; path = "Pod/Classes/Lifecycle/Framework/UIViewController+Lifecycle.swift"; sourceTree = ""; }; + BD6721E414F5E4895627210AFB5397AC /* Tracking.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tracking.swift; path = Sources/Tracking.swift; sourceTree = ""; }; + BDF0BD64F7D053FC261E77000D9D5B27 /* pb_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_encode.c; sourceTree = ""; }; + BE03FBD1AE757BEDE8D7B21466965FD1 /* NSDictionary+FIRMessaging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+FIRMessaging.h"; path = "Firebase/Messaging/NSDictionary+FIRMessaging.h"; sourceTree = ""; }; + BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Swiftilities.xcconfig; sourceTree = ""; }; + C05C63DA5EBF6B109936FE6137E41737 /* Protobuf-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Protobuf-prefix.pch"; sourceTree = ""; }; + C0865174F215EE5541472B794F16EABD /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = objectivec/google/protobuf/SourceContext.pbobjc.m; sourceTree = ""; }; + C0CD839E48FC413F0F119BC2DF2B9FF2 /* SessionManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionManager.swift; path = Source/SessionManager.swift; sourceTree = ""; }; + C1364213BD031AD3BAD42D9E69571ADD /* FloatingPoint+Scale.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "FloatingPoint+Scale.swift"; path = "Pod/Classes/Math/FloatingPoint+Scale.swift"; sourceTree = ""; }; + C146F3AD61FC35B7C5ACADB293B2E5CF /* pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb.h; sourceTree = ""; }; + C1CD6931566B12098A093FE863131A16 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-acknowledgements.markdown"; sourceTree = ""; }; + C2105C94812B6214B154F54DCEDB72AC /* Protobuf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Protobuf.framework; path = Protobuf.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C382C33DB25925C6186211ACF6C39C64 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = iOS/Fabric.framework; sourceTree = ""; }; + C392AFDD980E1C6B8554B9CCE3D4F95A /* Api.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = objectivec/google/protobuf/Api.pbobjc.h; sourceTree = ""; }; + C395986E3E5F5139E1E2D48B13C6B14A /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-umbrella.h"; sourceTree = ""; }; + C3BE33C9694478A1505C09DAF4276BAA /* GULAppEnvironmentUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppEnvironmentUtil.m; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m; sourceTree = ""; }; + C3C63D9CD07021084D0B9C31ED0A87AA /* FABAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FABAttributes.h; path = iOS/Fabric.framework/Headers/FABAttributes.h; sourceTree = ""; }; + C4060169D4E6873CF1EEF2A457AC3BD6 /* GPBUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBUtilities.m; path = objectivec/GPBUtilities.m; sourceTree = ""; }; + C40BAC08597BADB1064666DF2633CF2D /* SDStatusBarOverriderPost9_3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost9_3.h; path = SDStatusBarManager/SDStatusBarOverriderPost9_3.h; sourceTree = ""; }; + C4B85119F40EE2D53CF9459420F29B53 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}.appstore.xcconfig"; sourceTree = ""; }; + C5090975983CFFFD9CB40E0075C0D038 /* FIRInstanceIDKeyPairUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeyPairUtilities.m; path = Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m; sourceTree = ""; }; + C513955DA0F2FA1EC966C5DCB86267DE /* FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceID.m; path = Firebase/InstanceID/FIRInstanceID.m; sourceTree = ""; }; + C8268059830026F500EAD6383BB19F88 /* de.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = de.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/de.lproj"; sourceTree = ""; }; + C84BD906EE42E9D43CBC7AE02AA3C2E3 /* Pods-Services.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Services.modulemap"; sourceTree = ""; }; + C88DB8688B47BE7D71F76B016AD52DA8 /* CurveProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CurveProvider.swift; path = Pod/Classes/Math/CurveProvider.swift; sourceTree = ""; }; + C9AE3F8C3C621FD1D0196F941D21A520 /* FirebaseMessaging-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseMessaging-umbrella.h"; sourceTree = ""; }; + CB5E05211C1CC74484FAD2D8B97F2437 /* IBGReplies.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGReplies.h; path = Instabug.framework/Headers/IBGReplies.h; sourceTree = ""; }; + CC67002EE29757073391E2064F1BD0E6 /* SDStatusBarOverriderPost12_0.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDStatusBarOverriderPost12_0.m; path = SDStatusBarManager/SDStatusBarOverriderPost12_0.m; sourceTree = ""; }; + CCE4EFC833EB090ACE8EAA95D8F1FB5D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + CCEEB9D362BE4122040EB3458E5009F9 /* FirebaseCore.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCore.modulemap; sourceTree = ""; }; + CD626DB394FDD0FF51FD012D20A334F0 /* SDStatusBarManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarManager.h; path = SDStatusBarManager/SDStatusBarManager.h; sourceTree = ""; }; + CDE72026FE9260A75C5737785EC261F2 /* OHHTTPStubs.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = OHHTTPStubs.modulemap; sourceTree = ""; }; + CE04EB1BD0E0D76A2673A8C0C3366119 /* FIRInstanceIDAuthKeyChain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthKeyChain.h; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h; sourceTree = ""; }; + CE2FA012779DEECE2BC6CC90C6E90407 /* FieldValidator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FieldValidator.swift; path = Pod/Classes/Forms/FieldValidator.swift; sourceTree = ""; }; + CE3DE9896DF364A9A8E70FBF3411CAAD /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = Firebase/Core/Private/FIRComponent.h; sourceTree = ""; }; + CEC8FF8EB54F243F318CF7B7F16F7278 /* FirebaseCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCore.h; path = Firebase/Core/Public/FirebaseCore.h; sourceTree = ""; }; + CF22CC9C8607DFE61523790B4E8080FC /* Compatability.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Compatability.swift; path = Source/Compatability.swift; sourceTree = ""; }; + CFF7EEAD7E8E9673C73848326928A6CA /* FIRInteropParameterNames.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInteropParameterNames.h; path = Interop/Analytics/Public/FIRInteropParameterNames.h; sourceTree = ""; }; + D2B4AA2B21255F7A6AA09F0E059321BF /* FIROptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptions.h; path = Firebase/Core/Public/FIROptions.h; sourceTree = ""; }; + D33CE071F3F3081B71DA145EC68A99E8 /* StylisticAlternates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StylisticAlternates.swift; path = Sources/StylisticAlternates.swift; sourceTree = ""; }; + D362F402CE5684297570016D7825F239 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Request.swift; path = Source/Request.swift; sourceTree = ""; }; + D3761200331DF867B994EFC4B6F238B8 /* CLSStackFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSStackFrame.h; path = iOS/Crashlytics.framework/Headers/CLSStackFrame.h; sourceTree = ""; }; + D3CAB6FE3C8CDCA5DBD77435EA5A937D /* IBGReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGReport.h; path = Instabug.framework/Headers/IBGReport.h; sourceTree = ""; }; + D436B935FFA96DDB042376CB5C11E29E /* FIRVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVersion.h; path = Firebase/Core/Private/FIRVersion.h; sourceTree = ""; }; + D46CD8B2E3B48A9900B0D54DC022F51E /* FIRIMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRIMessageCode.h; path = Firebase/InstanceID/FIRIMessageCode.h; sourceTree = ""; }; + D4DEEAB8E3E3054E7C33B89FFE01EF18 /* Alamofire-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-prefix.pch"; sourceTree = ""; }; + D50A2051D90DCC03E026A0A56A46F1E0 /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBRuntimeTypes.h; path = objectivec/GPBRuntimeTypes.h; sourceTree = ""; }; + D5DE97AD0E8D2A97E134344E7227B548 /* FIRInstanceIDAuthKeyChain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthKeyChain.m; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m; sourceTree = ""; }; + D5EB134AFDFBA28F3347C088E94F3AA1 /* GtalkExtensions.pbobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GtalkExtensions.pbobjc.h; path = Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h; sourceTree = ""; }; + D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.xcconfig; sourceTree = ""; }; + D7500D2B23B7DC69CCA7B61577BEAD0D /* Protobuf-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Protobuf-dummy.m"; sourceTree = ""; }; + D7DEB68026091907EB2EBB5D82C47A00 /* FIRMessagingUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingUtilities.m; path = Firebase/Messaging/FIRMessagingUtilities.m; sourceTree = ""; }; + D7E5680FC53E7E9F3D5CDFD636890134 /* GPBCodedInputStream_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedInputStream_PackagePrivate.h; path = objectivec/GPBCodedInputStream_PackagePrivate.h; sourceTree = ""; }; + D7EC6B48A447510995672266B84A0112 /* Empty.pbobjc.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = objectivec/google/protobuf/Empty.pbobjc.m; sourceTree = ""; }; + D8D631A479FBF2CC1551FFD90D0D6CCF /* GULMutableDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULMutableDictionary.h; path = GoogleUtilities/Network/Private/GULMutableDictionary.h; sourceTree = ""; }; + D9011FC16F020AA7453970FDC70281F4 /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBArray_PackagePrivate.h; path = objectivec/GPBArray_PackagePrivate.h; sourceTree = ""; }; + D91C93EC98E43B5CACE58587FC5A08E4 /* FirebaseCore-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCore-Info.plist"; sourceTree = ""; }; + D9A9C2C923605432B520F3DCE9D1F43C /* nanopb.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = nanopb.modulemap; sourceTree = ""; }; + DA1CB779343A19D8C026EA3A9FD492D0 /* OHHTTPStubsMethodSwizzling.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsMethodSwizzling.h; path = OHHTTPStubs/Sources/NSURLSession/OHHTTPStubsMethodSwizzling.h; sourceTree = ""; }; + DA2E57EB3CB3312081676A46F7238B24 /* AdaptiveStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptiveStyle.swift; path = Sources/UIKit/AdaptiveStyle.swift; sourceTree = ""; }; + DB1194551671BF12886B8DECFEC28149 /* FIRInstanceIDKeychain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeychain.m; path = Firebase/InstanceID/FIRInstanceIDKeychain.m; sourceTree = ""; }; + DB5BD78F6D7A28ACB840F946DCBA826F /* OHHTTPStubs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubs.h; path = OHHTTPStubs/Sources/OHHTTPStubs.h; sourceTree = ""; }; + DB6E2DA2A7458E3619DF8D70A1EE9011 /* FIRInstanceIDKeychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeychain.h; path = Firebase/InstanceID/FIRInstanceIDKeychain.h; sourceTree = ""; }; + DC604E06843C199B7238C7ECCDD65231 /* GULNetwork.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetwork.m; path = GoogleUtilities/Network/GULNetwork.m; sourceTree = ""; }; + DCF0EDF0E175A8ABAE1DC6C2A8C67270 /* Validation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Validation.swift; path = Source/Validation.swift; sourceTree = ""; }; + DD6A6E8BEA17526E69B7E7C440D290E2 /* UIWindow+RootViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+RootViewController.swift"; path = "Pod/Classes/RootViewController/UIWindow+RootViewController.swift"; sourceTree = ""; }; + DE16395C09D232F30431F9810A0872D2 /* IBGBugReporting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IBGBugReporting.h; path = Instabug.framework/Headers/IBGBugReporting.h; sourceTree = ""; }; + DE1C7DAA26B8EA104B1A50DE2EC3AF35 /* XMLBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XMLBuilder.swift; path = Sources/XMLBuilder.swift; sourceTree = ""; }; + DE6910A0DE802228534590DFC11D90C2 /* FIRInstanceIDCheckinStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinStore.h; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.h; sourceTree = ""; }; + DEE2591C629B8D1D99F7EB621AFE24BA /* CubicBezier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CubicBezier.swift; path = Pod/Classes/Math/CubicBezier.swift; sourceTree = ""; }; + DFDA0DE503139F615A5FB983A7BAFD1A /* en.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = en.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/en.lproj"; sourceTree = ""; }; + E02A8313137BB858673B63F616E21827 /* FIRAnalyticsInteropListener.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsInteropListener.h; path = Interop/Analytics/Public/FIRAnalyticsInteropListener.h; sourceTree = ""; }; + E036B66F0200BB21E6A3C50B4A98D7C8 /* UIColor+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIColor+Helpers.swift"; path = "Pod/Classes/ColorHelpers/UIColor+Helpers.swift"; sourceTree = ""; }; + E07B09F7C15576A3A444C774F45026FA /* FontInspector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FontInspector.swift; path = Sources/FontInspector.swift; sourceTree = ""; }; + E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Crashlytics.xcconfig; sourceTree = ""; }; + E19C54CB57055FAC1B7EC1A332B36AE1 /* FIRMessagingPersistentSyncMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingPersistentSyncMessage.h; path = Firebase/Messaging/FIRMessagingPersistentSyncMessage.h; sourceTree = ""; }; + E1FE7B5BE33FDB3387A107014CDD4C22 /* Platform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Platform.swift; path = Sources/Platform.swift; sourceTree = ""; }; + E274690FABF5774F0512B21622B9BAD0 /* GPBExtensionInternals.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionInternals.m; path = objectivec/GPBExtensionInternals.m; sourceTree = ""; }; + E27982EA462CEA4BDA8EC7253E091FB9 /* FIRInteropEventNames.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInteropEventNames.h; path = Interop/Analytics/Public/FIRInteropEventNames.h; sourceTree = ""; }; + E2B37DD9690B667E67C7B749014FDAE6 /* FIRMessagingLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingLogger.h; path = Firebase/Messaging/FIRMessagingLogger.h; sourceTree = ""; }; + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCore.framework; path = FirebaseCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2E3405DF921FD6575E7698CA8B86D62 /* FIRInstanceIDCheckinPreferences.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences.h; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h; sourceTree = ""; }; + E2FDAAF328CFC1916BD31D012F33FA11 /* CGSize+DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CGSize+DeviceSize.swift"; path = "Pod/Classes/DeviceSize/CGSize+DeviceSize.swift"; sourceTree = ""; }; + E32BE18C7E79232857089AE39A09A626 /* ANSCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ANSCompatibility.h; path = iOS/Crashlytics.framework/Headers/ANSCompatibility.h; sourceTree = ""; }; + E3AE805A7D220717142177291A6563DD /* FIRMessagingRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRegistrar.m; path = Firebase/Messaging/FIRMessagingRegistrar.m; sourceTree = ""; }; + E458A4DC6C3E79475F17EE8A2379E327 /* pb_common.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_common.c; sourceTree = ""; }; + E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Fabric.xcconfig; sourceTree = ""; }; + E4A4ECCE028DEB376DB17F98A1E4451E /* NSAttributedString+Adaptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+Adaptive.swift"; path = "Sources/UIKit/NSAttributedString+Adaptive.swift"; sourceTree = ""; }; + E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Protobuf.xcconfig; sourceTree = ""; }; + E5A2D89B160FEBC3EA6D9A26612606E7 /* UIStackView+Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIStackView+Helpers.swift"; path = "Pod/Classes/StackViewHelpers/UIStackView+Helpers.swift"; sourceTree = ""; }; + E689A6FA791FBDA83E75CA835495CE84 /* FIRMessagingRemoteNotificationsProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingRemoteNotificationsProxy.m; path = Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m; sourceTree = ""; }; + E6B719E9A14C1E430887BE3B805CDDE2 /* BetterButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BetterButton.swift; path = Pod/Classes/BetterButton/BetterButton.swift; sourceTree = ""; }; + E6D0C984DDF42A7E6B78C3EAE3C981CB /* GPBCodedOutputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBCodedOutputStream.h; path = objectivec/GPBCodedOutputStream.h; sourceTree = ""; }; + E735845AC66A0F18361E9CB0A620082A /* FIRMessagingDataMessageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessagingDataMessageManager.m; path = Firebase/Messaging/FIRMessagingDataMessageManager.m; sourceTree = ""; }; + E73E251E3CF96E1495BE3EC085526D94 /* GULNSData+zlib.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GULNSData+zlib.m"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.m"; sourceTree = ""; }; + E774767ADA7D8B661ACBB80E499003DD /* FIRMessaging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMessaging.m; path = Firebase/Messaging/FIRMessaging.m; sourceTree = ""; }; + E7BDF86CE64C4E407EBF8A73A20C6EF3 /* GULNetworkLoggerProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkLoggerProtocol.h; path = GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h; sourceTree = ""; }; + E82C57A8834CD3A374E5E52A9DEBA80E /* GPBUnknownField.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBUnknownField.m; path = objectivec/GPBUnknownField.m; sourceTree = ""; }; + E862D618BF042EA8A06C94B566412A7A /* pb_encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_encode.h; sourceTree = ""; }; + E893CE5D8A792CBF4C835E33C903AB37 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = Firebase/Core/Private/FIRAppInternal.h; sourceTree = ""; }; + E8EE7F078656FABB8F6821D10FF994BB /* KeychainAccess.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = KeychainAccess.framework; path = KeychainAccess.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E90EB60C7D8B2CBCC777305E2D53F83F /* FIRInstanceIDVersionUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDVersionUtilities.m; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.m; sourceTree = ""; }; + EA144693E6BF8FE7CAC6E965241CE03D /* DefaultBehaviors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultBehaviors.swift; path = Pod/Classes/Lifecycle/Framework/DefaultBehaviors.swift; sourceTree = ""; }; + EA27AEAA510EE20594C0FCF896C53040 /* NSAttributedString+BonMot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+BonMot.swift"; path = "Sources/NSAttributedString+BonMot.swift"; sourceTree = ""; }; + EA44C89EDF2C4365821C353514E832DF /* FIRInstanceIDKeyPairStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeyPairStore.h; path = Firebase/InstanceID/FIRInstanceIDKeyPairStore.h; sourceTree = ""; }; + EC198B2667B7ACBED262624C674F40C0 /* FIRInstanceIDStringEncoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStringEncoding.m; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.m; sourceTree = ""; }; + EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = KeychainAccess.xcconfig; sourceTree = ""; }; + EC9B9847934B602C43CAC9AE7E2EBD36 /* AccessibilityHeadingLevel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityHeadingLevel.swift; path = Sources/AccessibilityHeadingLevel.swift; sourceTree = ""; }; + ECE318A98BEDBC9D92401EFDAE6EAC84 /* SDStatusBarOverriderPost11_0.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverriderPost11_0.h; path = SDStatusBarManager/SDStatusBarOverriderPost11_0.h; sourceTree = ""; }; + ED06C07D733F97DE5A5F19FEBD086CF5 /* InstabugCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = InstabugCore.h; path = Instabug.framework/Headers/InstabugCore.h; sourceTree = ""; }; + ED75C449FDA4BD587531DFEE93D42918 /* FIRMessagingUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingUtilities.h; path = Firebase/Messaging/FIRMessagingUtilities.h; sourceTree = ""; }; + ED9E474AFCCD58C67C788DC90A8A9AD0 /* SDStatusBarOverrider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDStatusBarOverrider.h; path = SDStatusBarManager/SDStatusBarOverrider.h; sourceTree = ""; }; + EEB3012499F8855E88664D9000D9DCE4 /* UIViewController+Deselection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Deselection.swift"; path = "Pod/Classes/Deselection/UIViewController+Deselection.swift"; sourceTree = ""; }; + EFBAAB841881AAAD3B071BA31361B288 /* GULReachabilityChecker+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULReachabilityChecker+Internal.h"; path = "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h"; sourceTree = ""; }; + F0821896A90AE916F84B3E580249644D /* FIRAppAssociationRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppAssociationRegistration.h; path = Firebase/Core/Private/FIRAppAssociationRegistration.h; sourceTree = ""; }; + F140B1E39A706719A3E80EF3EE95186D /* KeychainAccess-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "KeychainAccess-dummy.m"; sourceTree = ""; }; + F1EB3FA695D6D0C669DA36186435E474 /* FIRInstanceIDUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDUtilities.m; path = Firebase/InstanceID/FIRInstanceIDUtilities.m; sourceTree = ""; }; + F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseMessaging.xcconfig; sourceTree = ""; }; + F2181E7978D4D5EB57672242678285CA /* OHHTTPStubs+NSURLSessionConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubs+NSURLSessionConfiguration.m"; path = "OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m"; sourceTree = ""; }; + F33A6CC0B7DD266D5F442790D44ACD25 /* GPBDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPBDictionary.h; path = objectivec/GPBDictionary.h; sourceTree = ""; }; + F3787E17CA4EF4DC7B09E88A20DD9847 /* FirebaseCore-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCore-umbrella.h"; sourceTree = ""; }; + F44A4945BC33C7C54BB4A7520594B486 /* Image+Tinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Image+Tinting.swift"; path = "Sources/Image+Tinting.swift"; sourceTree = ""; }; + F4539DEEA1DD2E3E786DAB20A235E0B9 /* FIRInstanceIDKeyPairUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeyPairUtilities.h; path = Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h; sourceTree = ""; }; + F4E200831632A5DA6FE18A80ED063AA8 /* GPBMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPBMessage.m; path = objectivec/GPBMessage.m; sourceTree = ""; }; + F582E21899CB1B7DD3C29A9B5AB73287 /* OHPathHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHPathHelpers.h; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h; sourceTree = ""; }; + F5C73B87D6F5DBC36EAF4F5A2C11C0D8 /* OHHTTPStubs-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "OHHTTPStubs-Info.plist"; sourceTree = ""; }; + F6B71CAF2E55E96D2C79702EA17AC62E /* GULNetworkURLSession.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkURLSession.m; path = GoogleUtilities/Network/GULNetworkURLSession.m; sourceTree = ""; }; + F6D1E9800DF9216163D243A25E5A7E22 /* FIRApp.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRApp.h; path = Firebase/Core/Public/FIRApp.h; sourceTree = ""; }; + F6E6EBF71B53225C8F92782A7CC19944 /* StyleableUIElement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StyleableUIElement.swift; path = Sources/UIKit/StyleableUIElement.swift; sourceTree = ""; }; + F6EDB24AD1F08BD38D4E0B70CC036804 /* ru.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ru.lproj; path = "AppCenter-SDK-Apple/iOS/AppCenterDistributeResources.bundle/ru.lproj"; sourceTree = ""; }; + F7515C947EF6212592653822C53CC690 /* FIRInstanceIDCheckinPreferences.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinPreferences.m; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m; sourceTree = ""; }; + F7535A4C380C47E118395A613AF3D849 /* BonMot-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BonMot-umbrella.h"; sourceTree = ""; }; + F7696B90A3B3D1C34C7E852254DD74F1 /* Swiftilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Swiftilities.framework; path = Swiftilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F95AA7ACDE907999406636AE9140BF79 /* AdaptiveStyleTransformation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdaptiveStyleTransformation.swift; path = Sources/UIKit/AdaptiveStyleTransformation.swift; sourceTree = ""; }; + FA50610602A727B99D7294CFF81CC8E8 /* Pods-Services.sprint.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Services.sprint.xcconfig"; sourceTree = ""; }; + FA555490178D1D5AE635B8B28338E254 /* Swiftilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Swiftilities-prefix.pch"; sourceTree = ""; }; + FB1B0B49E7137AD9BBD29842C2A3A7BD /* FIRMessagingCodedInputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingCodedInputStream.h; path = Firebase/Messaging/FIRMessagingCodedInputStream.h; sourceTree = ""; }; + FB31D468DB67CC3C68E932FF60724283 /* NSURLRequest+HTTPBodyTesting.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSURLRequest+HTTPBodyTesting.m"; path = "OHHTTPStubs/Sources/NSURLSession/NSURLRequest+HTTPBodyTesting.m"; sourceTree = ""; }; + FB7E0D532911BBB43E2A8AF72818A0DD /* FIRMessagingDataMessageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMessagingDataMessageManager.h; path = Firebase/Messaging/FIRMessagingDataMessageManager.h; sourceTree = ""; }; + FB9EDEE9036C9154BDA9F866724100D7 /* Firebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Firebase.h; path = CoreOnly/Sources/Firebase.h; sourceTree = ""; }; + FCBFF9345F652100273AE93760F66435 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.develop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.develop.xcconfig"; sourceTree = ""; }; + FCCFBDA197465FE364E665276C2A88CA /* FirebaseInstanceID.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstanceID.modulemap; sourceTree = ""; }; + FCD38CBF4748B96190468E88F12A2064 /* Shapes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Shapes.swift; path = Pod/Classes/Shapes/Shapes.swift; sourceTree = ""; }; + FD58305059DB6EF784EF634B198DD3CB /* FIRInstanceIDTokenFetchOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenFetchOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m; sourceTree = ""; }; + FD757FD2EC6B3B19A20C755C1B166C5C /* Anchorage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Anchorage.modulemap; sourceTree = ""; }; + FDC9DBDC4B19FB33CDC14DE23114B21C /* FIRMMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMMessageCode.h; path = Firebase/Messaging/FIRMMessageCode.h; sourceTree = ""; }; + FF40060DC0344F915D924D3DC88F272D /* CGFloat+DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CGFloat+DeviceSize.swift"; path = "Pod/Classes/DeviceSize/CGFloat+DeviceSize.swift"; sourceTree = ""; }; + FF710E85F020077130E558211B5B8D8A /* FIRDependency.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDependency.m; path = Firebase/Core/FIRDependency.m; sourceTree = ""; }; + FF86C6514C399C0918A89B10C69289BA /* AcknowledgementViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AcknowledgementViewController.swift; path = Pod/Classes/Acknowledgements/AcknowledgementViewController.swift; sourceTree = ""; }; + FFC35B00BCB6D00D5DC095E60BA6F8D5 /* DeviceSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeviceSize.swift; path = Pod/Classes/DeviceSize/DeviceSize.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 07E3F9AF597FEC90D3D85283E3E5DA0A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D86C6E7427763F4CC75403A37ECB547 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0D430FA595C12BF6C51B1E5D7DA62489 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E237EA812A181AA46ABC963AC29854A5 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1EAA3BD0F5BEEE46CCBAA84201853CB8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D05E35FCFD0AD588208B9A3258ED8F9C /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 255C7B5ED5FE9184B51E5BED246FA3DD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E9687A54B05381DCB9BAAEA72366EA7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 28D36CD0B6FFBB03EEF67B156AEE1B4C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6B02408E859D41775E7C99C72211E233 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 32D9EDE9ED3871400CB94EF9184C0D6D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 04EF7CA88D2E1D49B56D74409399559A /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3ABCC0FD127A6AC59FE23898248C80CF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B26BD92ADC60A9F477AF155252F41C61 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4071E424BB335DEAE15B6918D860D684 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 45E7C2C769D51937061338A69BEE2316 /* Foundation.framework in Frameworks */, + CDE4C38B065973A40B8B7C844D236F86 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 726B5C2231D21F110E448BFD5292F6A1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A85388EF392B19C59DC3C5F54AE550BB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 74C2CDA0B2C1E3C0ACC15492B3B38619 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2723FECBFB4E4EE1EC645516FBB232D4 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 96338CCDB13BC8D010311E35BC765F14 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F58012B0BEE8E73287F2A68FEDAD92B2 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A2696FAB0EC2BE55C4464984FF5957B7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D80417305501039BA0BDDB62948E193 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9CBED312356F3CEFCFBBCD19C51292D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BAB7813CCBF7A137B84D0EAFC620B6DA /* CoreData.framework in Frameworks */, + 0F8CD4F146F1C58231026AAF09FAC5EE /* Foundation.framework in Frameworks */, + F387A6A0B4F0712AB31A31AF06E1437D /* MessageUI.framework in Frameworks */, + 1C3586AF524004892635EFD9A2F411EC /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AAEE8989AA8CAA1C579BE02343C9D362 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1077DE8C92C90C40F4D8ECE47B48EDB8 /* Foundation.framework in Frameworks */, + 7EEA98DF6EA7BC488FC2C7DC4579BD86 /* Security.framework in Frameworks */, + 148F3B7A2FF4E9CAC78C9E5AB0286CBB /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B18D41FB07D1B0D40F34100516637DCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CAE0EBE0C0215C8BD9ACB0BD0562526F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C5AF32A927179B590C49D6A14BF9158E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F833EC5D09A5161EE957E89F80A80BC7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DEB02DD77A9565F861100EC194EA6E99 /* CFNetwork.framework in Frameworks */, + 9FBAB5AB3AFE3F48C77BAD0033828124 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 008F18918E7698B497FF8188729031AD /* Sourcery */ = { + isa = PBXGroup; + children = ( + 788A2F1337113677CD6B6F0562BEACE1 /* Support Files */, + ); + name = Sourcery; + path = Sourcery; + sourceTree = ""; + }; + 008F623D5F4F4DAC4CE6F23C456144BD /* iOS */ = { + isa = PBXGroup; + children = ( + 6010A7276EC10495D966DCFE5E3C113E /* CFNetwork.framework */, + 8A467A3E9E3137B15241AA445AAA69D3 /* CoreData.framework */, + 4377A59FBAC44CE260030EDE8A1916B9 /* Foundation.framework */, + 2FA78D05699B3A7B758DCA452BE2C72E /* MessageUI.framework */, + 2207F5B391C14F1738C82A01AFB21DD1 /* Security.framework */, + CCE4EFC833EB090ACE8EAA95D8F1FB5D /* SystemConfiguration.framework */, + 83C4EF8C36A8B13E3F3E12C79005F57A /* UIKit.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 009380C89EA1FF9D5353746EAEF1EEED /* Crashlytics */ = { + isa = PBXGroup; + children = ( + E32BE18C7E79232857089AE39A09A626 /* ANSCompatibility.h */, + 5674AE212A0219BB0B7D3C5798B9D7E6 /* Answers.h */, + 7DF716A590C33DA0E5141543D157C552 /* CLSAttributes.h */, + AD4B1920B3B7BA2136B85A1738A0948B /* CLSLogging.h */, + 6CF234F15578D78CE0B9F963AE67AD0A /* CLSReport.h */, + D3761200331DF867B994EFC4B6F238B8 /* CLSStackFrame.h */, + 31ADA9CE18EE4DD7B2A1D3B81C8C8B97 /* Crashlytics.h */, + 972401FA47F7EB697BFBC5DE4DAA0651 /* Frameworks */, + 658C4AB79E2F1A8A07EAE776B3CC23B7 /* Support Files */, + ); + name = Crashlytics; + path = Crashlytics; + sourceTree = ""; + }; + 02309E965B34DCCD4D31C8903492D26F /* Support Files */ = { + isa = PBXGroup; + children = ( + 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/SwiftLint"; + sourceTree = ""; + }; + 02616AE4D5C78B93D9285050DF9BB523 /* Acknowledgements */ = { + isa = PBXGroup; + children = ( + 91A527A11C0F5C0E19DEF21E7B9C7F7E /* AcknowledgementsListViewController.swift */, + 3D6419DC93CAC1E865DD9A730B5C8623 /* AcknowledgementsListViewModel.swift */, + FF86C6514C399C0918A89B10C69289BA /* AcknowledgementViewController.swift */, + ); + name = Acknowledgements; + sourceTree = ""; + }; + 0399B942A602E396575791AC8C00C305 /* Support Files */ = { + isa = PBXGroup; + children = ( + BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/SwiftGen"; + sourceTree = ""; + }; + 03C52F83D51E179A4C50733DEECC309F /* FirebaseAnalyticsInterop */ = { + isa = PBXGroup; + children = ( + 511A6AAEF7B2FA3135202FCC07BF3E65 /* FIRAnalyticsInterop.h */, + E02A8313137BB858673B63F616E21827 /* FIRAnalyticsInteropListener.h */, + E27982EA462CEA4BDA8EC7253E091FB9 /* FIRInteropEventNames.h */, + CFF7EEAD7E8E9673C73848326928A6CA /* FIRInteropParameterNames.h */, + 4E81DF758C7837257EC6D514FD5F7CF6 /* Support Files */, + ); + name = FirebaseAnalyticsInterop; + path = FirebaseAnalyticsInterop; + sourceTree = ""; + }; + 05B1CA5F6FC7AE0E1EC3D2B58262045F /* KeychainAccess */ = { + isa = PBXGroup; + children = ( + 7D3E35ACC5108C1B4DEF24DD53900541 /* Keychain.swift */, + 4C3E423F1295AD2DB253BFC225128A1B /* Support Files */, + ); + name = KeychainAccess; + path = KeychainAccess; + sourceTree = ""; + }; + 0DA3027D10365E88FAE40797BBE0183B /* Deselection */ = { + isa = PBXGroup; + children = ( + EEB3012499F8855E88664D9000D9DCE4 /* UIViewController+Deselection.swift */, + ); + name = Deselection; + sourceTree = ""; + }; + 1107F56DAC35E1270FAD72DE01F6E7C2 /* Support Files */ = { + isa = PBXGroup; + children = ( + B1032898B87F1DAFA71E47C7FCB2E415 /* BonMot.modulemap */, + 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */, + 0055556FD5940D94B5719D2CE306ED83 /* BonMot-dummy.m */, + 15A36FCCB6649BA511408B3F1D946285 /* BonMot-Info.plist */, + 5079F288993DCE2E3F57BD1ECD985F0E /* BonMot-prefix.pch */, + F7535A4C380C47E118395A613AF3D849 /* BonMot-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/BonMot"; + sourceTree = ""; + }; + 13A10E37013F0F0D3C8A35C9A9D41EA0 /* Compatibility */ = { + isa = PBXGroup; + children = ( + AFE96786D662F36B014DB2976712E52D /* Compatibility.swift */, + ); + name = Compatibility; + sourceTree = ""; + }; + 13EF57D50F79CFF13C4996257901FDCC /* Environment */ = { + isa = PBXGroup; + children = ( + 5439C399E40C811A0CC58CD80BF419DB /* GULAppEnvironmentUtil.h */, + C3BE33C9694478A1505C09DAF4276BAA /* GULAppEnvironmentUtil.m */, + ); + name = Environment; + sourceTree = ""; + }; + 1B6124501CF65ED3F6A2AD1A93DBAC2D /* Swiftilities */ = { + isa = PBXGroup; + children = ( + 8685EDF6DBF9F3844A945C3B5F860AB9 /* AboutView */, + 52411C2325EA0E6639195CA9110A2234 /* AccessibilityHelpers */, + 02616AE4D5C78B93D9285050DF9BB523 /* Acknowledgements */, + AB4E2AFBBBBF559816C14051C59A22D0 /* BetterButton */, + 3A6DE26E8120CFC94EB0439625F7E334 /* ColorHelpers */, + 13A10E37013F0F0D3C8A35C9A9D41EA0 /* Compatibility */, + 5D975087B778CF0E10D511A544EC1BDC /* CoreDataStack */, + 0DA3027D10365E88FAE40797BBE0183B /* Deselection */, + 41BE4ED90D51A0C0F569F368E71DE98B /* DeviceSize */, + BE2E0F88645A73CD5BA9E99C1452EAEE /* FormattedTextField */, + A253B1E80FBA3C2BDD64EBC7F7DA3107 /* Forms */, + 9AC8E57272E0D480F3376E031CF9D360 /* HairlineView */, + 989DC329BA99D7559AF31C340D4FB904 /* ImageHelpers */, + 8FECC04822D33D646019B4479EA366F9 /* Keyboard */, + E09CF835A9CE9B38B033D04BE754B8C6 /* LicenseFormatter */, + C27D89BC0C94CADF409F60D4FB950035 /* Lifecycle */, + F04C2CDACCB32D83923281C298391F52 /* Logging */, + 2502596E810E33BBF0AA7B645BEEBD83 /* Math */, + F207982E6DE213CFE74F9EF7393F63A1 /* RootViewController */, + A0704D01E12AD83ADCAF5B229CE99161 /* Shapes */, + 6D2197C24F0848C862E51C94CF51A420 /* StackViewHelpers */, + A303943FD81E6344A959EF2275877C3B /* Support Files */, + 872C1397FD565D4C0B9EFDBBCED2AAAF /* TableViewHelpers */, + 8B8A98ECF03760402D075F38389B3988 /* TintedButton */, + FC97710BA2AAAA3C677BBC481F15EDAE /* Views */, + ); + name = Swiftilities; + path = Swiftilities; + sourceTree = ""; + }; + 1C939FBA6FABCCA30B1290EE3ACA9D09 /* Firebase */ = { + isa = PBXGroup; + children = ( + 4F0A8C75F385295E95A8A89975B92862 /* CoreOnly */, + 525AB3E395182778A970F9C5207657AD /* Support Files */, + ); + name = Firebase; + path = Firebase; + sourceTree = ""; + }; + 1CA59AED19FCBF816340C45A5F720DFF /* OHHTTPStubs */ = { + isa = PBXGroup; + children = ( + 2C08EFBA82D103166090522B94C4FE5D /* Core */, + 3246FB6EFFC4F5883B7C267801F2F1D1 /* JSON */, + B7C8A5E2542B08353007D5D146E3951A /* NSURLSession */, + 9F3FB97F3B837239BF3776F5642D3884 /* OHPathHelpers */, + 4FA174D92C9CCB6E07FD3C9C66C9F781 /* Support Files */, + B51FA2DAB550422A08450335F068110D /* Swift */, + ); + name = OHHTTPStubs; + path = OHHTTPStubs; + sourceTree = ""; + }; + 22012F4F0899CC6365FA911D9C7ADA3E /* MethodSwizzler */ = { + isa = PBXGroup; + children = ( + 6407CC37ECE767179AE4ED00301D5C52 /* GULOriginalIMPConvenienceMacros.h */, + 47EBEF062D1954D670444D5FB49CB050 /* GULSwizzler.h */, + A668229ECF671E377647F4DE649FE2D9 /* GULSwizzler.m */, + ); + name = MethodSwizzler; + sourceTree = ""; + }; + 230DD97E2682539EBF5CBB6EFCAB3D1B /* Support Files */ = { + isa = PBXGroup; + children = ( + D9A9C2C923605432B520F3DCE9D1F43C /* nanopb.modulemap */, + 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */, + AD9FCFD914EDA9CDBDE1BA40686E48E0 /* nanopb-dummy.m */, + 5BE4AF9D183DD4AA86ED02D801EC64FA /* nanopb-Info.plist */, + 8750CA9FEFAD9991DCE303273D306351 /* nanopb-prefix.pch */, + 22D8C3460BFD762A935246A9445DDDB6 /* nanopb-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/nanopb"; + sourceTree = ""; + }; + 24067F61C33DB58975E3961238A8DDF5 /* AppDelegateSwizzler */ = { + isa = PBXGroup; + children = ( + 60057B688B56F5C62D15997BB9EDEFDD /* GULAppDelegateSwizzler.h */, + 6DF740D3ACE024C9F6487F0DBFBBC4B7 /* GULAppDelegateSwizzler.m */, + 7F492B106E8EB1E2C72059F4CEC2ADF4 /* GULAppDelegateSwizzler_Private.h */, + 0D8C01D7DC37A7E86CB6EB912842D669 /* GULLoggerCodes.h */, + ); + name = AppDelegateSwizzler; + sourceTree = ""; + }; + 2502596E810E33BBF0AA7B645BEEBD83 /* Math */ = { + isa = PBXGroup; + children = ( + 526F1F36C6164054C3753D3E4D5C5C6B /* Clamping.swift */, + DEE2591C629B8D1D99F7EB621AFE24BA /* CubicBezier.swift */, + C88DB8688B47BE7D71F76B016AD52DA8 /* CurveProvider.swift */, + C1364213BD031AD3BAD42D9E69571ADD /* FloatingPoint+Scale.swift */, + ); + name = Math; + sourceTree = ""; + }; + 2516CFCC31378C0E7AD42AB3AEFD5046 /* Support Files */ = { + isa = PBXGroup; + children = ( + 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */, + 2DA62A31E606D66A0A8DF99FFB00CB54 /* ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/AppCenter"; + sourceTree = ""; + }; + 28FF4F61E9D98CE24E3756A1DB302AA4 /* Distribute */ = { + isa = PBXGroup; + children = ( + 524CDDEC3E70D2318C9B6BBF8351CCFF /* Frameworks */, + 4EC2D36F6022B2118DC1A8040605C49F /* Resources */, + ); + name = Distribute; + sourceTree = ""; + }; + 2BC40A9034E168E418BAA7541218D456 /* SimulatorStatusMagic */ = { + isa = PBXGroup; + children = ( + CD626DB394FDD0FF51FD012D20A334F0 /* SDStatusBarManager.h */, + 65DFDCD7CA8EB72916D84A809A50C7FD /* SDStatusBarManager.m */, + ED9E474AFCCD58C67C788DC90A8A9AD0 /* SDStatusBarOverrider.h */, + 76848D31B6A54F9167B3E81B2B157273 /* SDStatusBarOverriderPost10_0.h */, + 94F243E68DA74E3EF1064781840A6375 /* SDStatusBarOverriderPost10_0.m */, + 1997495D70A0AFDD3D4437EFFABE3048 /* SDStatusBarOverriderPost10_3.h */, + 21921F807B4B34CE95F4333954EF9330 /* SDStatusBarOverriderPost10_3.m */, + ECE318A98BEDBC9D92401EFDAE6EAC84 /* SDStatusBarOverriderPost11_0.h */, + AD72DEE352EC54E08A0DDA10EEDB3D49 /* SDStatusBarOverriderPost11_0.m */, + 322AE82498430F3AA39C51C2BC4FB15F /* SDStatusBarOverriderPost12_0.h */, + CC67002EE29757073391E2064F1BD0E6 /* SDStatusBarOverriderPost12_0.m */, + 53F88E4F0E3A11E9B5D721DEEDEB2F09 /* SDStatusBarOverriderPost8_3.h */, + 180977BDD0E3E3ED4CC91DF5BCD29868 /* SDStatusBarOverriderPost8_3.m */, + 13EF5B0944ABC90005395BF63E59D1B9 /* SDStatusBarOverriderPost9_0.h */, + 047E636E2BACE2765A28ADD8F0A0E5CA /* SDStatusBarOverriderPost9_0.m */, + C40BAC08597BADB1064666DF2633CF2D /* SDStatusBarOverriderPost9_3.h */, + AD7C3AE346CDF47C559CAA1E29D38819 /* SDStatusBarOverriderPost9_3.m */, + 1F937168226D3E9CD0FDFCA1B32629DA /* SDStatusBarOverriderPre8_3.h */, + 433FD3F0C39CB9CDDF7F51F624242518 /* SDStatusBarOverriderPre8_3.m */, + 9B39C83358AAA4C9B0BE04FCA31A4DD4 /* Support Files */, + ); + name = SimulatorStatusMagic; + path = SimulatorStatusMagic; + sourceTree = ""; + }; + 2C08EFBA82D103166090522B94C4FE5D /* Core */ = { + isa = PBXGroup; + children = ( + 4FCB1518EBBFFD314F997C63F2AE720F /* Compatibility.h */, + DB5BD78F6D7A28ACB840F946DCBA826F /* OHHTTPStubs.h */, + 9BE96B90011674F188BAA0598BD91B53 /* OHHTTPStubs.m */, + 5A3F12E1757587C015AB1F285348CFAB /* OHHTTPStubsResponse.h */, + 3C9D78BDFE3971F2EF43F1EE93290481 /* OHHTTPStubsResponse.m */, + ); + name = Core; + sourceTree = ""; + }; + 2F42D4BF0DDF237686424E3A4EF51E70 /* FirebaseMessaging */ = { + isa = PBXGroup; + children = ( + 9A68AA6C83230BBFED7CC97DA09A987B /* FirebaseMessaging.h */, + 5D6FB40F4F28DA6BC422DDDDBBC7CDA6 /* FirebaseMessaging.h */, + 9C8948FFD9D354F2001C98CEE8B45E08 /* FIRMessaging.h */, + E774767ADA7D8B661ACBB80E499003DD /* FIRMessaging.m */, + 8E5AF5D638A5E46AC1F536B0D9FC686E /* FIRMessaging_Private.h */, + 98DE82806BC35C7A7C3ACBCF0C7B379F /* FIRMessagingAnalytics.h */, + 9AAD5AF881A90E6C8ABB964271CD3D7F /* FIRMessagingAnalytics.m */, + 7930F6E4B1DBA1F8B3A51893DC47D6D9 /* FIRMessagingCheckinService.h */, + 44A66697CB999F1B94BE112FF3F6082E /* FIRMessagingCheckinService.m */, + 2C51C1D95A23094AED0ABE47DE23F077 /* FIRMessagingClient.h */, + 318F5854818D012A621F4EE3E8A310B3 /* FIRMessagingClient.m */, + FB1B0B49E7137AD9BBD29842C2A3A7BD /* FIRMessagingCodedInputStream.h */, + 986EF3488689CACCCB183285A1909D6A /* FIRMessagingCodedInputStream.m */, + 0951EED81BCFA0803E2B141DE332E11D /* FIRMessagingConnection.h */, + AD183A51FD1FF965003291AC5F048C14 /* FIRMessagingConnection.m */, + 360D12ED7F2D4981DBE39DE4FCDC76A3 /* FIRMessagingConstants.h */, + 67E6336A4DE03D2B54BB4E2D5C377405 /* FIRMessagingConstants.m */, + 6B4A56D8EB5978D426BDC59DC1AA5E2C /* FIRMessagingContextManagerService.h */, + 6C651771BDA251122C0517F98DD229C4 /* FIRMessagingContextManagerService.m */, + FB7E0D532911BBB43E2A8AF72818A0DD /* FIRMessagingDataMessageManager.h */, + E735845AC66A0F18361E9CB0A620082A /* FIRMessagingDataMessageManager.m */, + B8E0195AADB4B77EBBA26DCB16A7ADB1 /* FIRMessagingDefines.h */, + B1EEA6318B7652582ADC0248EF0E862A /* FIRMessagingDelayedMessageQueue.h */, + 468332F23F5D358DB2288F3934AEC350 /* FIRMessagingDelayedMessageQueue.m */, + BC07246B7DD7857DA18E71CDAD1E01D4 /* FIRMessagingExtensionHelper.h */, + 6CFEFDB61382511167CBE5BFA016DFF7 /* FIRMessagingExtensionHelper.m */, + 29977CBD0F0F1352A376A22E58D14F56 /* FIRMessagingInternalUtilities.h */, + E2B37DD9690B667E67C7B749014FDAE6 /* FIRMessagingLogger.h */, + 1500A31AAD61B6B55D1541CEC1F8B821 /* FIRMessagingLogger.m */, + 5F9E4B9D5FF21ED1F4AB75BA5BA13598 /* FIRMessagingPacketQueue.h */, + 3BA9EA5998AA76F74EE798C3CBBECA9D /* FIRMessagingPacketQueue.m */, + 662B607559C369907018526CD34E7A82 /* FIRMessagingPendingTopicsList.h */, + B67FA446F6A78388566D90BDD02B2175 /* FIRMessagingPendingTopicsList.m */, + E19C54CB57055FAC1B7EC1A332B36AE1 /* FIRMessagingPersistentSyncMessage.h */, + 356BEB97A3924CA7A9EFA6E39B529298 /* FIRMessagingPersistentSyncMessage.m */, + 7798FFAA50C6E5C495F258D8A51AFCF9 /* FIRMessagingPubSub.h */, + 949C61608ACEFB9BB47A141E428D5CED /* FIRMessagingPubSub.m */, + 849FE1C62D5BADA93D12508A10FFB88A /* FIRMessagingPubSubRegistrar.h */, + ABF027D832F3CFAAE988298C13DB25CF /* FIRMessagingPubSubRegistrar.m */, + B5D090276832D4024D8B3A5568BEA4DE /* FIRMessagingReceiver.h */, + 7750A59221DB77FAF80CF7B06B985ABA /* FIRMessagingReceiver.m */, + 5725B7F7891756CBC38A7C3FFBA0605D /* FIRMessagingRegistrar.h */, + E3AE805A7D220717142177291A6563DD /* FIRMessagingRegistrar.m */, + 7240263E6AB16234AD51BABC7BEDBFD0 /* FIRMessagingRemoteNotificationsProxy.h */, + E689A6FA791FBDA83E75CA835495CE84 /* FIRMessagingRemoteNotificationsProxy.m */, + 846244C0EC47A8A7BE9B1E2506F77C50 /* FIRMessagingRmq2PersistentStore.h */, + 1F13E67C41FD3508A00AC0A6F6CA8A43 /* FIRMessagingRmq2PersistentStore.m */, + 8BCBB2D56D50E44BD77F0169A7F75E7B /* FIRMessagingRmqManager.h */, + 92F4855C80835F853383873CD1CB78B4 /* FIRMessagingRmqManager.m */, + 37E010E6C2F14B116AD0A6E40D547F39 /* FIRMessagingSecureSocket.h */, + 67D20FEE4726CCB26A931435C6F7F8D6 /* FIRMessagingSecureSocket.m */, + B7A5E48BA4D6DE7CABBE36B040019834 /* FIRMessagingSyncMessageManager.h */, + B4625D667AFBD9425C3A79449E05F451 /* FIRMessagingSyncMessageManager.m */, + 88C8386A2D3A8315518D7FC2CF01A15B /* FIRMessagingTopicOperation.h */, + 6D0CAF61CDA366988A208A7B3648AB10 /* FIRMessagingTopicOperation.m */, + 623AE596A3622CB246F0C91BF962A5EA /* FIRMessagingTopicsCommon.h */, + ED75C449FDA4BD587531DFEE93D42918 /* FIRMessagingUtilities.h */, + D7DEB68026091907EB2EBB5D82C47A00 /* FIRMessagingUtilities.m */, + 4707DEF6F61CF955E8D0164566D43983 /* FIRMessagingVersionUtilities.h */, + 3C1809F979F3942E4C48A86D0F20B10B /* FIRMessagingVersionUtilities.m */, + FDC9DBDC4B19FB33CDC14DE23114B21C /* FIRMMessageCode.h */, + 12D36157D372B866FB49CE4288D881E3 /* GtalkCore.pbobjc.h */, + 21518DB69A5249884D47AA1C030D65A1 /* GtalkCore.pbobjc.m */, + D5EB134AFDFBA28F3347C088E94F3AA1 /* GtalkExtensions.pbobjc.h */, + B4C8749E960A855A7C7965EC2BA8218A /* GtalkExtensions.pbobjc.m */, + BE03FBD1AE757BEDE8D7B21466965FD1 /* NSDictionary+FIRMessaging.h */, + BA59223CF8122E668F27A492727DA05A /* NSDictionary+FIRMessaging.m */, + 5F619742AF64CEB785C8717E281D3DA7 /* NSError+FIRMessaging.h */, + 7E51F53C43C26EC84AD204A2DF58797C /* NSError+FIRMessaging.m */, + A2BA946DCE676E2A736992A6D7F61F5D /* Support Files */, + ); + name = FirebaseMessaging; + path = FirebaseMessaging; + sourceTree = ""; + }; + 309669BC4003FB5E733750D429EB9CA5 /* Support Files */ = { + isa = PBXGroup; + children = ( + 9E5694DFDF2C9E53E5A1BB537671493B /* Protobuf.modulemap */, + E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */, + D7500D2B23B7DC69CCA7B61577BEAD0D /* Protobuf-dummy.m */, + 1D68553FA13FBC980DEA48AD8F4FF33C /* Protobuf-Info.plist */, + C05C63DA5EBF6B109936FE6137E41737 /* Protobuf-prefix.pch */, + 8A2450A9AC3AEDEE3814CEC1893EBE3F /* Protobuf-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Protobuf"; + sourceTree = ""; + }; + 3246FB6EFFC4F5883B7C267801F2F1D1 /* JSON */ = { + isa = PBXGroup; + children = ( + 247C04FA03FB22629ED9C337A195F8F6 /* OHHTTPStubsResponse+JSON.h */, + 73047CD3A9D6F102084B6565479FD975 /* OHHTTPStubsResponse+JSON.m */, + ); + name = JSON; + sourceTree = ""; + }; + 37EAF90413960A018228B0E598F8F0EA /* Protobuf */ = { + isa = PBXGroup; + children = ( + 22D1FCC1043B4DD3CEA939877906ECD8 /* Any.pbobjc.h */, + 2E5D20BCCFC283EBF43CD654944F92FB /* Any.pbobjc.m */, + C392AFDD980E1C6B8554B9CCE3D4F95A /* Api.pbobjc.h */, + 809A9FA0958DAAB72D85475C1510B28C /* Api.pbobjc.m */, + 5805433E9EE4075EBAE342A288525AD4 /* Duration.pbobjc.h */, + B53967F27884E26D24DE4B390642290C /* Duration.pbobjc.m */, + B3B80947892AFE99F690D90E0E6F7A0C /* Empty.pbobjc.h */, + D7EC6B48A447510995672266B84A0112 /* Empty.pbobjc.m */, + 3B333D83F4602F037A199CE1061A7A79 /* FieldMask.pbobjc.h */, + B7873C854D420CA53D1BD7CE0700ACDC /* FieldMask.pbobjc.m */, + 4A12FC33DD08260C9C378A9C2A227833 /* GPBArray.h */, + ADB4B0347B4897392B2245F4E44D0AC1 /* GPBArray.m */, + D9011FC16F020AA7453970FDC70281F4 /* GPBArray_PackagePrivate.h */, + 670326828280195E95A7805733428555 /* GPBBootstrap.h */, + 4D827CD1FACB9020945F3B62976196F5 /* GPBCodedInputStream.h */, + 536F55571CB5D4E8C4CD313EFFC98897 /* GPBCodedInputStream.m */, + D7E5680FC53E7E9F3D5CDFD636890134 /* GPBCodedInputStream_PackagePrivate.h */, + E6D0C984DDF42A7E6B78C3EAE3C981CB /* GPBCodedOutputStream.h */, + 8942E740881A6372C900E36D68EAF4CB /* GPBCodedOutputStream.m */, + 1064EA2176F4289B3F2DC02849A83825 /* GPBCodedOutputStream_PackagePrivate.h */, + 168D0C5421335ACFB5EBB53C584D8B5D /* GPBDescriptor.h */, + 4B1D3820BB2870B22224C025F97B495A /* GPBDescriptor.m */, + 399A0F9FCF8F163E53341ADFC13A530F /* GPBDescriptor_PackagePrivate.h */, + F33A6CC0B7DD266D5F442790D44ACD25 /* GPBDictionary.h */, + 8A10B633A7F6F7DB8565FCD54B2F6015 /* GPBDictionary.m */, + 0D7113D1B1F68315334A5D6E5C78151A /* GPBDictionary_PackagePrivate.h */, + 780F31022D4CCCEEEF6B0433A8907F93 /* GPBExtensionInternals.h */, + E274690FABF5774F0512B21622B9BAD0 /* GPBExtensionInternals.m */, + 7DF32B5609DBC1BE477D33A94686964D /* GPBExtensionRegistry.h */, + 37D1089A0FB89C55B768CC26C804A7B2 /* GPBExtensionRegistry.m */, + 0B179EF2E474E501FD5650C4ADF83782 /* GPBMessage.h */, + F4E200831632A5DA6FE18A80ED063AA8 /* GPBMessage.m */, + 01FC0E2DFCCF55217572DC39EA5C6163 /* GPBMessage_PackagePrivate.h */, + 789045C4CD88187B1C8B6952AD65877D /* GPBProtocolBuffers.h */, + 6FF4D0CB4786B5D9882E4D069869A3CF /* GPBProtocolBuffers_RuntimeSupport.h */, + BB5DFE1F01AFD7800F073ECA808AD019 /* GPBRootObject.h */, + 8B4A5B8EBEA544128E7C93E89A933ACE /* GPBRootObject.m */, + 9EE85328C2AA2BE65AC5476B9A3A4B9A /* GPBRootObject_PackagePrivate.h */, + D50A2051D90DCC03E026A0A56A46F1E0 /* GPBRuntimeTypes.h */, + 58BC5AB95FAF621615835A4436B69D8C /* GPBUnknownField.h */, + E82C57A8834CD3A374E5E52A9DEBA80E /* GPBUnknownField.m */, + 2DF285A229D15CB8F3DFBB3DD3DC7884 /* GPBUnknownField_PackagePrivate.h */, + B7B04D349B7F6EF4AB5D84952D2A53DE /* GPBUnknownFieldSet.h */, + B2127ADF7134D22A7B41243F58B119B2 /* GPBUnknownFieldSet.m */, + 7BE9D1869AAADCD42062E01D5D3C87C8 /* GPBUnknownFieldSet_PackagePrivate.h */, + 7C5A26153063FDC9CF29CACEBFDCE19B /* GPBUtilities.h */, + C4060169D4E6873CF1EEF2A457AC3BD6 /* GPBUtilities.m */, + 8466929A49CE3221978EB36183FD35BA /* GPBUtilities_PackagePrivate.h */, + 20D53BC1D9D046786E39FFC97B7B43A7 /* GPBWellKnownTypes.h */, + 258251CAB54F309E8E640653850C4B32 /* GPBWellKnownTypes.m */, + 053874D026363AC0A03A09A01558AD61 /* GPBWireFormat.h */, + 814B71C2E085A900096EC6AECF6B4CE3 /* GPBWireFormat.m */, + 5BD0138F17C5CEC5217CDE58354221B3 /* SourceContext.pbobjc.h */, + C0865174F215EE5541472B794F16EABD /* SourceContext.pbobjc.m */, + 7A62C867EDE3F5810D57F99ED04E9BA0 /* Struct.pbobjc.h */, + 7D5ABA89BFABB034F15503FA4EA2C665 /* Struct.pbobjc.m */, + 2FDE57075083813209769DB1ECBA097C /* Timestamp.pbobjc.h */, + 9D75377169BF1143EF206F74484FC1F0 /* Timestamp.pbobjc.m */, + 05E39D129D919E418F8D526AC9591021 /* Type.pbobjc.h */, + 1F6EBA7C6997FF0B01735341A694592F /* Type.pbobjc.m */, + 4DE6952B80D386C75EA01A7B003A923F /* Wrappers.pbobjc.h */, + 38337959621A4D9065BD17ACB25371AD /* Wrappers.pbobjc.m */, + 309669BC4003FB5E733750D429EB9CA5 /* Support Files */, + ); + name = Protobuf; + path = Protobuf; + sourceTree = ""; + }; + 3A6DE26E8120CFC94EB0439625F7E334 /* ColorHelpers */ = { + isa = PBXGroup; + children = ( + E036B66F0200BB21E6A3C50B4A98D7C8 /* UIColor+Helpers.swift */, + ); + name = ColorHelpers; + sourceTree = ""; + }; + 3B2DC82F6FC98950B2D602286A0BA4DA /* UserDefaults */ = { + isa = PBXGroup; + children = ( + 807724545CC9FBB3B33672198DD057ED /* GULUserDefaults.h */, + 36624989E8CA8F0B22557AD8E3ACAEEF /* GULUserDefaults.m */, + ); + name = UserDefaults; + sourceTree = ""; + }; + 41BE4ED90D51A0C0F569F368E71DE98B /* DeviceSize */ = { + isa = PBXGroup; + children = ( + FF40060DC0344F915D924D3DC88F272D /* CGFloat+DeviceSize.swift */, + E2FDAAF328CFC1916BD31D012F33FA11 /* CGSize+DeviceSize.swift */, + FFC35B00BCB6D00D5DC095E60BA6F8D5 /* DeviceSize.swift */, + ); + name = DeviceSize; + sourceTree = ""; + }; + 4B759243E3FC5DFD9399CEDDF79EB5AD /* Support Files */ = { + isa = PBXGroup; + children = ( + 7F9F3C7A180A25601F10CA6EDA5435A1 /* Alamofire.modulemap */, + B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */, + 01CDC0351ED7CEC107FB8A77489F99CE /* Alamofire-dummy.m */, + 35BA4A04ECE9B5B06B1021FB70BBB8E9 /* Alamofire-Info.plist */, + D4DEEAB8E3E3054E7C33B89FFE01EF18 /* Alamofire-prefix.pch */, + 55D73A9343E88A26AE65A4223D8C07DF /* Alamofire-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Alamofire"; + sourceTree = ""; + }; + 4C3E423F1295AD2DB253BFC225128A1B /* Support Files */ = { + isa = PBXGroup; + children = ( + 784571D4952D4EA67F2018794826B771 /* KeychainAccess.modulemap */, + EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */, + F140B1E39A706719A3E80EF3EE95186D /* KeychainAccess-dummy.m */, + 444803A0ADD399B49C628CFC2947F5D0 /* KeychainAccess-Info.plist */, + ADD85DBCA961517182D229A520E707A7 /* KeychainAccess-prefix.pch */, + 9EF45F089BAE93FE828CD9688AA8CA8A /* KeychainAccess-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/KeychainAccess"; + sourceTree = ""; + }; + 4C4557B4DD2C0EF6C0E4D60D96ADD8C3 /* Network */ = { + isa = PBXGroup; + children = ( + D8D631A479FBF2CC1551FFD90D0D6CCF /* GULMutableDictionary.h */, + 3B5E83DF94AA1871CCE123E6D44F0B70 /* GULMutableDictionary.m */, + 71D265F83D526F8D4CBAF591F57A1C35 /* GULNetwork.h */, + DC604E06843C199B7238C7ECCDD65231 /* GULNetwork.m */, + 9221AE50CB51C7E8CD93A956CC3EA7C2 /* GULNetworkConstants.h */, + 3E381DBDE829EC743F4F0A730A0EA4E5 /* GULNetworkConstants.m */, + E7BDF86CE64C4E407EBF8A73A20C6EF3 /* GULNetworkLoggerProtocol.h */, + 35D0212C3DBD3EB9B48F92FE6E705124 /* GULNetworkMessageCode.h */, + 8239448521ADE6944ED02A4E4E8F83C5 /* GULNetworkURLSession.h */, + F6B71CAF2E55E96D2C79702EA17AC62E /* GULNetworkURLSession.m */, + ); + name = Network; + sourceTree = ""; + }; + 4E81DF758C7837257EC6D514FD5F7CF6 /* Support Files */ = { + isa = PBXGroup; + children = ( + 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalyticsInterop"; + sourceTree = ""; + }; + 4EC2D36F6022B2118DC1A8040605C49F /* Resources */ = { + isa = PBXGroup; + children = ( + 74BE747D93A2FF0D9596DFEB89B88506 /* cs.lproj */, + C8268059830026F500EAD6383BB19F88 /* de.lproj */, + DFDA0DE503139F615A5FB983A7BAFD1A /* en.lproj */, + 9917CC431DC36BB3D118B1AA7A204319 /* es.lproj */, + 829D6EBA77079A9CFF95E76253E1B175 /* fr.lproj */, + B7AD2BE9A6C9E2298E7917BF8FD6E425 /* it.lproj */, + 0F5EF93A5BE453909C31B9C6554C95CD /* ja.lproj */, + 1683A78B7B9007625AE95AAE42A96663 /* ko.lproj */, + 842142B2B14A0BA4AFCC17CBAC0F7C98 /* pl.lproj */, + 0172526E6D3CEFD172AD72474B7F1B03 /* pt.lproj */, + F6EDB24AD1F08BD38D4E0B70CC036804 /* ru.lproj */, + AB8C0F48EBA2E62C0D0D696427AAF734 /* tr.lproj */, + 9217346EC5CA9E35B7D5CC7A1AC82A9B /* zh-Hans.lproj */, + B732E75D7C970C6F08CDE5C6AFDF8702 /* zh-Hant.lproj */, + ); + name = Resources; + sourceTree = ""; + }; + 4F0A8C75F385295E95A8A89975B92862 /* CoreOnly */ = { + isa = PBXGroup; + children = ( + FB9EDEE9036C9154BDA9F866724100D7 /* Firebase.h */, + ); + name = CoreOnly; + sourceTree = ""; + }; + 4FA174D92C9CCB6E07FD3C9C66C9F781 /* Support Files */ = { + isa = PBXGroup; + children = ( + CDE72026FE9260A75C5737785EC261F2 /* OHHTTPStubs.modulemap */, + 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */, + B7A403AA64C0558925444F207EEADE76 /* OHHTTPStubs-dummy.m */, + F5C73B87D6F5DBC36EAF4F5A2C11C0D8 /* OHHTTPStubs-Info.plist */, + 741B01C4F4159696D4237F6F4D3A98BB /* OHHTTPStubs-prefix.pch */, + 2F6F1BBF9B142B5EF49F87D2D044E829 /* OHHTTPStubs-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/OHHTTPStubs"; + sourceTree = ""; + }; + 51A6420B90C1B77281AFA830BC68F078 /* BonMot */ = { + isa = PBXGroup; + children = ( + EC9B9847934B602C43CAC9AE7E2EBD36 /* AccessibilityHeadingLevel.swift */, + AF9BA9F1FCE9E687C9236562D28FBBF6 /* AdaptableTextContainer.swift */, + DA2E57EB3CB3312081676A46F7238B24 /* AdaptiveStyle.swift */, + F95AA7ACDE907999406636AE9140BF79 /* AdaptiveStyleTransformation.swift */, + 4E3D53C87F3183ECB9828E9F2CC13CEF /* AttributedStringTransformation.swift */, + 52C88D2EB51952A1D85A0AB4AD8FE1D6 /* Compatibility.swift */, + 5D93E1401B7CC5204F8F2112E6F2DF1A /* Composable.swift */, + 2707310D83A1EE6275AED80C0CF694FE /* ContextualAlternates.swift */, + B74880F26CD1B4204F6539C5B5502D2E /* EmbeddedTransformation.swift */, + A45D8D0A1979A555EFB7FFB40FE9E3B3 /* Emphasis.swift */, + 9EF280833555D9A6C3AB807C1BBEF193 /* FontFeatures.swift */, + E07B09F7C15576A3A444C774F45026FA /* FontInspector.swift */, + F44A4945BC33C7C54BB4A7520594B486 /* Image+Tinting.swift */, + 8C4EB1163B98FFAB7C42AB21C3ACF776 /* Ligatures.swift */, + 793A451BCFED3B0D33EF91ABA0E76DC0 /* MutableCopying.swift */, + 288D811BFAFF4D05B72871868528971C /* NamedStyles.swift */, + E4A4ECCE028DEB376DB17F98A1E4451E /* NSAttributedString+Adaptive.swift */, + EA27AEAA510EE20594C0FCF896C53040 /* NSAttributedString+BonMot.swift */, + E1FE7B5BE33FDB3387A107014CDD4C22 /* Platform.swift */, + 9E603AE6FAEA107641D9E8499AD28ACD /* Special.swift */, + 786594362231C88055784CE1F30F160D /* StringStyle.swift */, + 6E2CFBCCEE9CCE0907B805548198E2D4 /* StringStyle+Part.swift */, + F6E6EBF71B53225C8F92782A7CC19944 /* StyleableUIElement.swift */, + D33CE071F3F3081B71DA145EC68A99E8 /* StylisticAlternates.swift */, + 8FA9AF149F192E34E86DF398F93B6819 /* Tab.swift */, + 9457CFFC68284D195CF10F91CD0AB794 /* Tab+Adaptive.swift */, + 5112CE97A821E9C641D75D1ADAC3EB32 /* TextAlignmentConstraint.swift */, + BD6721E414F5E4895627210AFB5397AC /* Tracking.swift */, + 7852EA1E7C25798259AEA5BCE126639F /* Tracking+Adaptive.swift */, + 23F5E88F86F777E70C48C646149BA42B /* Transform.swift */, + 9D4DE2FA59344D4592D75A8D5A4137CE /* UIKit+AdaptableTextContainerSupport.swift */, + 547CDF4449B3AF5D1990F54FD639448E /* UIKit+Helpers.swift */, + DE1C7DAA26B8EA104B1A50DE2EC3AF35 /* XMLBuilder.swift */, + 1107F56DAC35E1270FAD72DE01F6E7C2 /* Support Files */, + ); + name = BonMot; + path = BonMot; + sourceTree = ""; + }; + 52411C2325EA0E6639195CA9110A2234 /* AccessibilityHelpers */ = { + isa = PBXGroup; + children = ( + 075A60A7C92F557056B739FD7E6BD32C /* AccessibilityHelpers.swift */, + ); + name = AccessibilityHelpers; + sourceTree = ""; + }; + 524CDDEC3E70D2318C9B6BBF8351CCFF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0124BA8F81579A732104EE20E5A04876 /* AppCenterDistribute.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 525AB3E395182778A970F9C5207657AD /* Support Files */ = { + isa = PBXGroup; + children = ( + 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Firebase"; + sourceTree = ""; + }; + 5D975087B778CF0E10D511A544EC1BDC /* CoreDataStack */ = { + isa = PBXGroup; + children = ( + A39DC1AB08D7C48D33B0213FC070EE91 /* CoreDataStack.swift */, + ); + name = CoreDataStack; + sourceTree = ""; + }; + 61E1FBD62BF31EF9C5C6FCF8C2475554 /* Support Files */ = { + isa = PBXGroup; + children = ( + 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Instabug"; + sourceTree = ""; + }; + 639C45A86FA428194EE4AA78ED28FDCC /* SwiftGen */ = { + isa = PBXGroup; + children = ( + 0399B942A602E396575791AC8C00C305 /* Support Files */, + ); + name = SwiftGen; + path = SwiftGen; + sourceTree = ""; + }; + 658C4AB79E2F1A8A07EAE776B3CC23B7 /* Support Files */ = { + isa = PBXGroup; + children = ( + E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Crashlytics"; + sourceTree = ""; + }; + 662F353757E6B7E31DA01A696E1A2E2C /* Support Files */ = { + isa = PBXGroup; + children = ( + CCEEB9D362BE4122040EB3458E5009F9 /* FirebaseCore.modulemap */, + 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */, + A78104E9B1CB747B9ACC895D21681C1E /* FirebaseCore-dummy.m */, + D91C93EC98E43B5CACE58587FC5A08E4 /* FirebaseCore-Info.plist */, + F3787E17CA4EF4DC7B09E88A20DD9847 /* FirebaseCore-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCore"; + sourceTree = ""; + }; + 6A4D2FEE841CDA2E21B0A6D31767C6E3 /* GoogleUtilities */ = { + isa = PBXGroup; + children = ( + 24067F61C33DB58975E3961238A8DDF5 /* AppDelegateSwizzler */, + 13EF57D50F79CFF13C4996257901FDCC /* Environment */, + 7B23925A72D583C0812A0471748128AD /* Logger */, + 22012F4F0899CC6365FA911D9C7ADA3E /* MethodSwizzler */, + 4C4557B4DD2C0EF6C0E4D60D96ADD8C3 /* Network */, + CEC3374FD169D13C3E074C43021D181B /* NSData+zlib */, + F52DE65EA93C92C1F1F94D5B0BC29E6A /* Reachability */, + 993188936FF4518DE583518FC0A00FFC /* Support Files */, + 3B2DC82F6FC98950B2D602286A0BA4DA /* UserDefaults */, + ); + name = GoogleUtilities; + path = GoogleUtilities; + sourceTree = ""; + }; + 6BDBCD98184ECE9E56EC1D563CFE1CA1 /* FirebaseInstanceID */ = { + isa = PBXGroup; + children = ( + 0D5C9E49FD0B96CC5F0A774F637668F2 /* FirebaseInstanceID.h */, + D46CD8B2E3B48A9900B0D54DC022F51E /* FIRIMessageCode.h */, + 677C759A60BA1A68EC54588ED16024FD /* FIRInstanceID.h */, + C513955DA0F2FA1EC966C5DCB86267DE /* FIRInstanceID.m */, + 10D13A0F900275F0E08660D22CBD3BD7 /* FIRInstanceID+Private.h */, + 18DE3A66023F031C118C9FA1671ACC93 /* FIRInstanceID+Private.m */, + 8F4E12C03F40438969454920C49D2013 /* FIRInstanceID_Private.h */, + 046CA33B599DC985AC83516113232E99 /* FIRInstanceIDAPNSInfo.h */, + 88B5959D5B7A3E36DDEF6EA561F00502 /* FIRInstanceIDAPNSInfo.m */, + CE04EB1BD0E0D76A2673A8C0C3366119 /* FIRInstanceIDAuthKeyChain.h */, + D5DE97AD0E8D2A97E134344E7227B548 /* FIRInstanceIDAuthKeyChain.m */, + 2B76802A61020D8F2FF87DBC22F95501 /* FIRInstanceIDAuthService.h */, + 781146DAC6F2B33CBAB88F5B7480DA3C /* FIRInstanceIDAuthService.m */, + B8D3618FE4C32D4ADBE22D247745AB5F /* FIRInstanceIDBackupExcludedPlist.h */, + 466630EDA0868AA0AB1CEBACE48F76AB /* FIRInstanceIDBackupExcludedPlist.m */, + E2E3405DF921FD6575E7698CA8B86D62 /* FIRInstanceIDCheckinPreferences.h */, + F7515C947EF6212592653822C53CC690 /* FIRInstanceIDCheckinPreferences.m */, + 8487A57EC520F91735649B13CF1455E4 /* FIRInstanceIDCheckinPreferences+Internal.h */, + 186880608DAD6477417FCC20081E68DF /* FIRInstanceIDCheckinPreferences+Internal.m */, + 1E28DADD6AFEF6A2BABCAA95C90585AE /* FIRInstanceIDCheckinPreferences_Private.h */, + 5215C876BC30D194764B41B21031B21F /* FIRInstanceIDCheckinService.h */, + 44001909662AEC3C8F8AB4E8044AB034 /* FIRInstanceIDCheckinService.m */, + DE6910A0DE802228534590DFC11D90C2 /* FIRInstanceIDCheckinStore.h */, + 0904254547F200171C92FAE60BF75E4B /* FIRInstanceIDCheckinStore.m */, + 9B49BB3E350F98DF8781264F7BB9D61B /* FIRInstanceIDCombinedHandler.h */, + 26880FF9FEB2270469CDC3F44CFC51BE /* FIRInstanceIDCombinedHandler.m */, + 11EF24F4E2A79E63296F2034D972DD0A /* FIRInstanceIDConstants.h */, + A48A79CAAFF110C87DF8BF807837AB83 /* FIRInstanceIDConstants.m */, + 30C8877C44A2A9CEF55FFA4B756AB34A /* FIRInstanceIDDefines.h */, + DB6E2DA2A7458E3619DF8D70A1EE9011 /* FIRInstanceIDKeychain.h */, + DB1194551671BF12886B8DECFEC28149 /* FIRInstanceIDKeychain.m */, + 1C37EAC158A77C4D6904556D7810ED89 /* FIRInstanceIDKeyPair.h */, + 56C526BDE19AC726B077CA91F4A3D248 /* FIRInstanceIDKeyPair.m */, + EA44C89EDF2C4365821C353514E832DF /* FIRInstanceIDKeyPairStore.h */, + 13811593551EEF5606EAEAC864156243 /* FIRInstanceIDKeyPairStore.m */, + F4539DEEA1DD2E3E786DAB20A235E0B9 /* FIRInstanceIDKeyPairUtilities.h */, + C5090975983CFFFD9CB40E0075C0D038 /* FIRInstanceIDKeyPairUtilities.m */, + BAEE38A7456029D2435589A2AB61BB54 /* FIRInstanceIDLogger.h */, + B348867894A4CE1D01EE3407670282AA /* FIRInstanceIDLogger.m */, + 9F64FB46C163A2D7EEDD531525ED4A3E /* FIRInstanceIDStore.h */, + 8F00E32E42A1E8D5237611B57EB97BFC /* FIRInstanceIDStore.m */, + 24FEA1649F859C025807618A170C83B1 /* FIRInstanceIDStringEncoding.h */, + EC198B2667B7ACBED262624C674F40C0 /* FIRInstanceIDStringEncoding.m */, + 78277DF682670FCB6D1E611B6DD72010 /* FIRInstanceIDTokenDeleteOperation.h */, + B94ED403343770A491208CD276342FF7 /* FIRInstanceIDTokenDeleteOperation.m */, + 5FD4F06E7B97586342DC5F130C93CAD6 /* FIRInstanceIDTokenFetchOperation.h */, + FD58305059DB6EF784EF634B198DD3CB /* FIRInstanceIDTokenFetchOperation.m */, + 5AC714289EA97E67199CA997655EAF27 /* FIRInstanceIDTokenInfo.h */, + 55C1593407CAC28F4349FBA65B0C1BD9 /* FIRInstanceIDTokenInfo.m */, + B80D74D41E215EDC00F1A0D8245EC63E /* FIRInstanceIDTokenManager.h */, + 661D315940B1DDA7A83242BBBB7CFCA3 /* FIRInstanceIDTokenManager.m */, + 6F5FE5A0393B7EA11DA9DBF03DDF5479 /* FIRInstanceIDTokenOperation.h */, + 08DA9B3BA661AA7124AE37AFA1396048 /* FIRInstanceIDTokenOperation.m */, + 571718858875E6D21B448DAAA8A43D00 /* FIRInstanceIDTokenOperation+Private.h */, + 7DF524EA9012A4ACFCAD0BF6C7247299 /* FIRInstanceIDTokenStore.h */, + 3739B5667A1C1B8452C08E5FB55014E5 /* FIRInstanceIDTokenStore.m */, + 0E1E27256DFC0F8898600F8DA01A1D3E /* FIRInstanceIDURLQueryItem.h */, + 45BCED46E7DDF7FBA46DB0CC8B1E58EB /* FIRInstanceIDURLQueryItem.m */, + A3AA81B96ABF2101A80128229B5253C0 /* FIRInstanceIDUtilities.h */, + F1EB3FA695D6D0C669DA36186435E474 /* FIRInstanceIDUtilities.m */, + 4B0940BB70F444E65F6DB52323B97369 /* FIRInstanceIDVersionUtilities.h */, + E90EB60C7D8B2CBCC777305E2D53F83F /* FIRInstanceIDVersionUtilities.m */, + 7E542A623F5A954B3F4D243CF8A4FB46 /* NSError+FIRInstanceID.h */, + 6EB8515E357A8EA23661EBCD579561C3 /* NSError+FIRInstanceID.m */, + E81AD734C1E0D7D9E60EBB121AB226B1 /* Support Files */, + ); + name = FirebaseInstanceID; + path = FirebaseInstanceID; + sourceTree = ""; + }; + 6D2197C24F0848C862E51C94CF51A420 /* StackViewHelpers */ = { + isa = PBXGroup; + children = ( + E5A2D89B160FEBC3EA6D9A26612606E7 /* UIStackView+Helpers.swift */, + ); + name = StackViewHelpers; + sourceTree = ""; + }; + 6F3EF0FA0969EBD80C6F4351AE01874E /* AppCenter */ = { + isa = PBXGroup; + children = ( + 7093ACAC5F51DA6AC7991BED779FAA8F /* Core */, + 28FF4F61E9D98CE24E3756A1DB302AA4 /* Distribute */, + 2516CFCC31378C0E7AD42AB3AEFD5046 /* Support Files */, + ); + name = AppCenter; + path = AppCenter; + sourceTree = ""; + }; + 6F7FBCC6A736AEF8531F507FBD9838DA /* encode */ = { + isa = PBXGroup; + children = ( + ); + name = encode; + sourceTree = ""; + }; + 7093ACAC5F51DA6AC7991BED779FAA8F /* Core */ = { + isa = PBXGroup; + children = ( + A8D54C77C0BEB46D88F469145C20DE6C /* Frameworks */, + ); + name = Core; + sourceTree = ""; + }; + 788A2F1337113677CD6B6F0562BEACE1 /* Support Files */ = { + isa = PBXGroup; + children = ( + 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Sourcery"; + sourceTree = ""; + }; + 7A06EBF1D3AE62AED0DC085715332089 /* Pods-Services */ = { + isa = PBXGroup; + children = ( + C84BD906EE42E9D43CBC7AE02AA3C2E3 /* Pods-Services.modulemap */, + 2B6941F28C59EA39D79CAAF8560210A4 /* Pods-Services-acknowledgements.markdown */, + 1FC6D095DAD42D44CCD8E75BCB2FE43F /* Pods-Services-acknowledgements.plist */, + AF4C07CB531C2A20C075F1E2F27F9807 /* Pods-Services-dummy.m */, + 73D447A7F190F1E1C93B83CA52F803B4 /* Pods-Services-Info.plist */, + 43F95FB28B3B3DDC58B3E70C591BD759 /* Pods-Services-umbrella.h */, + 1987EE9FAD1DBEC74F2716EA5DC6B2D0 /* Pods-Services.appstore.xcconfig */, + 63202DA0FE6824272136B2EC50F9FB63 /* Pods-Services.debug.xcconfig */, + 1358F7B95EC32C0D0017CE9DBF481067 /* Pods-Services.develop.xcconfig */, + FA50610602A727B99D7294CFF81CC8E8 /* Pods-Services.sprint.xcconfig */, + ); + name = "Pods-Services"; + path = "Target Support Files/Pods-Services"; + sourceTree = ""; + }; + 7B0CC8495563F9B10D302FDF8BE31E73 /* nanopb */ = { + isa = PBXGroup; + children = ( + C146F3AD61FC35B7C5ACADB293B2E5CF /* pb.h */, + E458A4DC6C3E79475F17EE8A2379E327 /* pb_common.c */, + 63782DD22D80D12F0478617EBF8A6E9E /* pb_common.h */, + BBF0EE4B9DF20FB5E0DF535FED448A7E /* pb_decode.c */, + 322D077B4897B4E6A8C083170A121575 /* pb_decode.h */, + BDF0BD64F7D053FC261E77000D9D5B27 /* pb_encode.c */, + E862D618BF042EA8A06C94B566412A7A /* pb_encode.h */, + FBB07FC05F11C073D5B30FFFF4FB1787 /* decode */, + 6F7FBCC6A736AEF8531F507FBD9838DA /* encode */, + 230DD97E2682539EBF5CBB6EFCAB3D1B /* Support Files */, + ); + name = nanopb; + path = nanopb; + sourceTree = ""; + }; + 7B23925A72D583C0812A0471748128AD /* Logger */ = { + isa = PBXGroup; + children = ( + 15D1AB7F35E8D9D69E2A3E30D0AFA1F1 /* GULLogger.h */, + 319AFABD7CD5670EEEE2D2BA15A360BD /* GULLogger.m */, + 2D45D29B213853B66B8B282991CCF083 /* GULLoggerLevel.h */, + ); + name = Logger; + sourceTree = ""; + }; + 7F7F3C5E8428F9EC082EB77C8B6C0743 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }} */ = { + isa = PBXGroup; + children = ( + B5579787CFCE1BC97D5EF0CCEB731C04 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap */, + C1CD6931566B12098A093FE863131A16 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-acknowledgements.markdown */, + 2DE296C57E7600238C8BE1E7BEE31B00 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-acknowledgements.plist */, + 9A572C6721447ABE0F589A4004BA6EFA /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-dummy.m */, + 598E11382120CC7243651B55798ADF64 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-frameworks.sh */, + 32FC646A39309A016A43413CF59D0AB3 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist */, + A1718A38D1F7426976B72AE548700F4E /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-resources.sh */, + 8F63F7236794D312ACB1F32E2BE55CA4 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-umbrella.h */, + C4B85119F40EE2D53CF9459420F29B53 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.appstore.xcconfig */, + 8CC134AECB569C629CF74E270D3E8FC3 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.debug.xcconfig */, + 4C3439A40A51D1DD58761BACB9331DD2 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.develop.xcconfig */, + 518BACD57DCD1AA45BE9270B8C5CF1B5 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.sprint.xcconfig */, + ); + name = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}"; + path = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}"; + sourceTree = ""; + }; + 8275CCB4E8732497B1021FCBC240F3C2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 008F623D5F4F4DAC4CE6F23C456144BD /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 82C0081EC4C54F0E3B87CF4659B2C78B /* GoogleAppMeasurement */ = { + isa = PBXGroup; + children = ( + E101FC07342B02BB434763AB5503FDF0 /* Frameworks */, + B73AC685A73B7CABCDF13699741B1462 /* Support Files */, + ); + name = GoogleAppMeasurement; + path = GoogleAppMeasurement; + sourceTree = ""; + }; + 85904E31CC5A94E382F8A1C5377D2253 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8EA90B335493CD691AF6F92A19615597 /* FIRAnalyticsConnector.framework */, + 82C3962E95811D63FBFBD722F2BD0204 /* FirebaseAnalytics.framework */, + 5BA55509BAF2F35EE0DDC61B513006A6 /* FirebaseCoreDiagnostics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8685EDF6DBF9F3844A945C3B5F860AB9 /* AboutView */ = { + isa = PBXGroup; + children = ( + 6F446B65463479D1A1BC7E615FB1DB21 /* AboutView.swift */, + 829A957DF3BA4C53A538E446773D71B8 /* AppInfo.swift */, + 6228C304CE54B8A03AEF3954707FB619 /* FeedbackPresenter.swift */, + ); + name = AboutView; + sourceTree = ""; + }; + 872C1397FD565D4C0B9EFDBBCED2AAAF /* TableViewHelpers */ = { + isa = PBXGroup; + children = ( + 6605561032963C6225A616C84441A72F /* IndexPath+Extensions.swift */, + 245165C00B0AB8EFA8DF3D2BBC1F3C8D /* TableSection.swift */, + 552F3B93D76BA12F543F0275D11FB3F6 /* UITableView+Extensions.swift */, + ); + name = TableViewHelpers; + sourceTree = ""; + }; + 8A454DADBEB04B4D31A42E8DFBD25E37 /* SwiftLint */ = { + isa = PBXGroup; + children = ( + 02309E965B34DCCD4D31C8903492D26F /* Support Files */, + ); + name = SwiftLint; + path = SwiftLint; + sourceTree = ""; + }; + 8B8A98ECF03760402D075F38389B3988 /* TintedButton */ = { + isa = PBXGroup; + children = ( + 3F5BB4D560F726BDE1F35DA184B1268B /* TintedButton.swift */, + ); + name = TintedButton; + sourceTree = ""; + }; + 8BDFEEE65FACF169A2EB85AE06AD1146 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests */ = { + isa = PBXGroup; + children = ( + 422359491E6C68A5FEFC4E916C0385EF /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap */, + 39011BD939C3832DBBFC0228D3EF5804 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-acknowledgements.markdown */, + AF915886F12CE018C123DBCE8092ECC5 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-acknowledgements.plist */, + 7E629EB70356C8FA1AD9781584EA8374 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-dummy.m */, + 95728BB595EBF3C2595CF132C9C7AAAC /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-frameworks.sh */, + 16C9E7ABD2EF227BB7684A8307667F72 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist */, + 781DC562E9BB6624DE3FB5B273AEF265 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-resources.sh */, + C395986E3E5F5139E1E2D48B13C6B14A /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-umbrella.h */, + 3CE8A623704EA768F5F5576533B75CC4 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.appstore.xcconfig */, + 300E24828164112EB400CCFD1E0D55B9 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.debug.xcconfig */, + FCBFF9345F652100273AE93760F66435 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.develop.xcconfig */, + 7B31944D9854B90AB402DAEBC2714BCB /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.sprint.xcconfig */, + ); + name = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests"; + path = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests"; + sourceTree = ""; + }; + 8D527B9C3DE0F3C4790F2C72704D59DC /* Pods */ = { + isa = PBXGroup; + children = ( + BC59AFE25F73D0ABD159E379B3DA14B5 /* Alamofire */, + AE6F222D95639EFAB3F51992DA3BAEB5 /* Anchorage */, + 6F3EF0FA0969EBD80C6F4351AE01874E /* AppCenter */, + 51A6420B90C1B77281AFA830BC68F078 /* BonMot */, + 009380C89EA1FF9D5353746EAEF1EEED /* Crashlytics */, + AAE112D8EBCF66234755E03D80A66A35 /* Fabric */, + 1C939FBA6FABCCA30B1290EE3ACA9D09 /* Firebase */, + 8D59FF043DE5F5E40B310E41E371B2B0 /* FirebaseAnalytics */, + 03C52F83D51E179A4C50733DEECC309F /* FirebaseAnalyticsInterop */, + D5A1FC161D50AE992042E65485320E60 /* FirebaseCore */, + 6BDBCD98184ECE9E56EC1D563CFE1CA1 /* FirebaseInstanceID */, + 2F42D4BF0DDF237686424E3A4EF51E70 /* FirebaseMessaging */, + 82C0081EC4C54F0E3B87CF4659B2C78B /* GoogleAppMeasurement */, + 6A4D2FEE841CDA2E21B0A6D31767C6E3 /* GoogleUtilities */, + C59A82E1D6A01A9AEE70D0221E9593F7 /* Instabug */, + 05B1CA5F6FC7AE0E1EC3D2B58262045F /* KeychainAccess */, + 7B0CC8495563F9B10D302FDF8BE31E73 /* nanopb */, + 1CA59AED19FCBF816340C45A5F720DFF /* OHHTTPStubs */, + 37EAF90413960A018228B0E598F8F0EA /* Protobuf */, + 2BC40A9034E168E418BAA7541218D456 /* SimulatorStatusMagic */, + 008F18918E7698B497FF8188729031AD /* Sourcery */, + 639C45A86FA428194EE4AA78ED28FDCC /* SwiftGen */, + 1B6124501CF65ED3F6A2AD1A93DBAC2D /* Swiftilities */, + 8A454DADBEB04B4D31A42E8DFBD25E37 /* SwiftLint */, + ); + name = Pods; + sourceTree = ""; + }; + 8D59FF043DE5F5E40B310E41E371B2B0 /* FirebaseAnalytics */ = { + isa = PBXGroup; + children = ( + 85904E31CC5A94E382F8A1C5377D2253 /* Frameworks */, + F7114582B168E212D19780C5CCFBEC19 /* Support Files */, + ); + name = FirebaseAnalytics; + path = FirebaseAnalytics; + sourceTree = ""; + }; + 8FECC04822D33D646019B4479EA366F9 /* Keyboard */ = { + isa = PBXGroup; + children = ( + 7558233F38BB01572FA6F6C87087DE05 /* Keyboard.swift */, + 365D0C4EEEA6C8DB030220CF3E73772A /* UIView+KeyboardLayoutGuide.swift */, + ); + name = Keyboard; + sourceTree = ""; + }; + 972401FA47F7EB697BFBC5DE4DAA0651 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0B8FDDE48F44189CC0D2FC2CAA0D5C49 /* Crashlytics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 989DC329BA99D7559AF31C340D4FB904 /* ImageHelpers */ = { + isa = PBXGroup; + children = ( + B8E677CF6BD8B668E00639F75526D6FE /* UIImage+Tinting.swift */, + ); + name = ImageHelpers; + sourceTree = ""; + }; + 993188936FF4518DE583518FC0A00FFC /* Support Files */ = { + isa = PBXGroup; + children = ( + 7FF09D8EFD37D437525F039619D3D763 /* GoogleUtilities.modulemap */, + 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */, + 44CE758ABDDC428058091BE3EF7C9451 /* GoogleUtilities-dummy.m */, + 4D0B98AEB62ED9CED697D20516060929 /* GoogleUtilities-Info.plist */, + 233D6E7BF9D19F75FCD75EB9691646DB /* GoogleUtilities-prefix.pch */, + A64AD290563189B5EC09536986EEA27C /* GoogleUtilities-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleUtilities"; + sourceTree = ""; + }; + 9AC8E57272E0D480F3376E031CF9D360 /* HairlineView */ = { + isa = PBXGroup; + children = ( + 9435CEF7CA7BCE866E215F71262E51F6 /* HairlineView.swift */, + ); + name = HairlineView; + sourceTree = ""; + }; + 9B39C83358AAA4C9B0BE04FCA31A4DD4 /* Support Files */ = { + isa = PBXGroup; + children = ( + 80F2752CD15387DAD8075D0DE08C9A48 /* SimulatorStatusMagic.modulemap */, + 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */, + 6EBEFE4F4DF5F7C86F8F3F2C30FC2380 /* SimulatorStatusMagic-dummy.m */, + 84DA61DFF1F0980689DC3F498047D530 /* SimulatorStatusMagic-Info.plist */, + 7579D1AD4020ED9620DFC5844850FF1E /* SimulatorStatusMagic-prefix.pch */, + 422661E817D097522D8B376CDBD2FD9C /* SimulatorStatusMagic-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/SimulatorStatusMagic"; + sourceTree = ""; + }; + 9EC0439B0FC7C4EEE4048EF00565EA88 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C382C33DB25925C6186211ACF6C39C64 /* Fabric.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9F3FB97F3B837239BF3776F5642D3884 /* OHPathHelpers */ = { + isa = PBXGroup; + children = ( + F582E21899CB1B7DD3C29A9B5AB73287 /* OHPathHelpers.h */, + 894FB1F3B5CAA20D3A8E5DA58FA415A3 /* OHPathHelpers.m */, + ); + name = OHPathHelpers; + sourceTree = ""; + }; + A0704D01E12AD83ADCAF5B229CE99161 /* Shapes */ = { + isa = PBXGroup; + children = ( + FCD38CBF4748B96190468E88F12A2064 /* Shapes.swift */, + ); + name = Shapes; + sourceTree = ""; + }; + A253B1E80FBA3C2BDD64EBC7F7DA3107 /* Forms */ = { + isa = PBXGroup; + children = ( + CE2FA012779DEECE2BC6CC90C6E90407 /* FieldValidator.swift */, + A52569BDA16818151E3735016A95C16B /* UIView+Lookup.swift */, + ); + name = Forms; + sourceTree = ""; + }; + A2BA946DCE676E2A736992A6D7F61F5D /* Support Files */ = { + isa = PBXGroup; + children = ( + 89A489E0FEA5C5815748A7017DDB2666 /* FirebaseMessaging.modulemap */, + F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */, + 1F16A3F715737A448BD6736FC7CE8C23 /* FirebaseMessaging-dummy.m */, + 5099DC3344B97A39551F2FD82C61B62E /* FirebaseMessaging-Info.plist */, + C9AE3F8C3C621FD1D0196F941D21A520 /* FirebaseMessaging-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseMessaging"; + sourceTree = ""; + }; + A303943FD81E6344A959EF2275877C3B /* Support Files */ = { + isa = PBXGroup; + children = ( + 1546A7379CB47F23D0B23E42B46F302D /* Swiftilities.modulemap */, + BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */, + 016ABA6E4EC051693A5A08A27FAAA7DC /* Swiftilities-dummy.m */, + 346C27A97925A47261C4B6AC76983CD3 /* Swiftilities-Info.plist */, + FA555490178D1D5AE635B8B28338E254 /* Swiftilities-prefix.pch */, + 88F89AA47577A480D576C38E3EDFADAA /* Swiftilities-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Swiftilities"; + sourceTree = ""; + }; + A8D54C77C0BEB46D88F469145C20DE6C /* Frameworks */ = { + isa = PBXGroup; + children = ( + B7010FC71D49408694A41D0B4A22E831 /* AppCenter.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + AAE112D8EBCF66234755E03D80A66A35 /* Fabric */ = { + isa = PBXGroup; + children = ( + C3C63D9CD07021084D0B9C31ED0A87AA /* FABAttributes.h */, + 935548E336DB715970FA91771AE5D568 /* Fabric.h */, + 9EC0439B0FC7C4EEE4048EF00565EA88 /* Frameworks */, + E97757579390FAE0C029F4AB98E7459C /* Support Files */, + ); + name = Fabric; + path = Fabric; + sourceTree = ""; + }; + AB4E2AFBBBBF559816C14051C59A22D0 /* BetterButton */ = { + isa = PBXGroup; + children = ( + E6B719E9A14C1E430887BE3B805CDDE2 /* BetterButton.swift */, + ); + name = BetterButton; + sourceTree = ""; + }; + AE6F222D95639EFAB3F51992DA3BAEB5 /* Anchorage */ = { + isa = PBXGroup; + children = ( + 13FC2F155F0438B5C95978061F39743F /* Anchorage.swift */, + 2F6E205211513A677E520BAD5BD8C183 /* AnchorGroupProvider.swift */, + CF22CC9C8607DFE61523790B4E8080FC /* Compatability.swift */, + 2CA2C241BE9B8942C2622A8288159183 /* Internal.swift */, + 5D2F76C4975A9F75ECFED7459246BDCE /* NSLayoutAnchor+MultiplierConstraints.swift */, + 968AD6C6067177F3FFBF4E22B5D62AFA /* Priority.swift */, + ECC016BE841E69D8F7164C18E603AB7D /* Support Files */, + ); + name = Anchorage; + path = Anchorage; + sourceTree = ""; + }; + B51FA2DAB550422A08450335F068110D /* Swift */ = { + isa = PBXGroup; + children = ( + 00D5703DE6D32E8BEE77AC1C2A64D12F /* OHHTTPStubsSwift.swift */, + ); + name = Swift; + sourceTree = ""; + }; + B73AC685A73B7CABCDF13699741B1462 /* Support Files */ = { + isa = PBXGroup; + children = ( + D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleAppMeasurement"; + sourceTree = ""; + }; + B7C8A5E2542B08353007D5D146E3951A /* NSURLSession */ = { + isa = PBXGroup; + children = ( + 92B3A83AF7CBD24CFB27352A8A473464 /* NSURLRequest+HTTPBodyTesting.h */, + FB31D468DB67CC3C68E932FF60724283 /* NSURLRequest+HTTPBodyTesting.m */, + F2181E7978D4D5EB57672242678285CA /* OHHTTPStubs+NSURLSessionConfiguration.m */, + DA1CB779343A19D8C026EA3A9FD492D0 /* OHHTTPStubsMethodSwizzling.h */, + B0DF923FAF38D4B7E93295F4F7B7E252 /* OHHTTPStubsMethodSwizzling.m */, + ); + name = NSURLSession; + sourceTree = ""; + }; + BC59AFE25F73D0ABD159E379B3DA14B5 /* Alamofire */ = { + isa = PBXGroup; + children = ( + 3D6B1D921CE2EF324C684690E9B44CD4 /* AFError.swift */, + 5D79D6EFCA519A3D859AD623DEEA3E97 /* Alamofire.swift */, + 773F43FA50FABF1CE0C562282F32D624 /* DispatchQueue+Alamofire.swift */, + 3CFCAB771CD0ED282F14A09984871047 /* MultipartFormData.swift */, + B11A4E7961F768D0892E18D1649C5FE4 /* NetworkReachabilityManager.swift */, + 26820BF7BDA3D0A1D104CE81E2CF5EEE /* Notifications.swift */, + 367EF090BA9D626CCBE6C72374BAB47B /* ParameterEncoding.swift */, + D362F402CE5684297570016D7825F239 /* Request.swift */, + 0AD7A8A7135C2FC81974892005E66656 /* Response.swift */, + A23C1F66FE104A9AB25DB49ABA41F52E /* ResponseSerialization.swift */, + 45D7EE49F14DA03DC27AA4631DE48483 /* Result.swift */, + 62F4647B8C0D1352B1C58A2CCAC8F8A1 /* ServerTrustPolicy.swift */, + 1248BFF6EDD2B0B1963D8E18335E0DCD /* SessionDelegate.swift */, + C0CD839E48FC413F0F119BC2DF2B9FF2 /* SessionManager.swift */, + 548F85D6FB2D9B296B3CB2FD0B313CDC /* TaskDelegate.swift */, + 0613D7FC4E5B1B63B0C08F9883F7B6CB /* Timeline.swift */, + DCF0EDF0E175A8ABAE1DC6C2A8C67270 /* Validation.swift */, + 4B759243E3FC5DFD9399CEDDF79EB5AD /* Support Files */, + ); + name = Alamofire; + path = Alamofire; + sourceTree = ""; + }; + BE2E0F88645A73CD5BA9E99C1452EAEE /* FormattedTextField */ = { + isa = PBXGroup; + children = ( + 2F85F03D3204EDFA79866F18C991616C /* FormattedTextField.swift */, + ); + name = FormattedTextField; + sourceTree = ""; + }; + C27D89BC0C94CADF409F60D4FB950035 /* Lifecycle */ = { + isa = PBXGroup; + children = ( + EA144693E6BF8FE7CAC6E965241CE03D /* DefaultBehaviors.swift */, + 5D1F592A03F29834A482A527C26C43F1 /* LifecycleBehaviorViewController.swift */, + 441C8E5411061099355CF78039DCB16A /* NavBarHairlineFadeBehavior.swift */, + 01502087710687B101E4DBC35B149B69 /* NavTitleTransitionBehavior.swift */, + BCDA99AA3900C0A75CF6AFE7E2BEF2A0 /* UIViewController+Lifecycle.swift */, + 0D70F6C27F2262A020CDFA6DBA6E0A95 /* ViewControllerLifecycleBehavior.swift */, + ); + name = Lifecycle; + sourceTree = ""; + }; + C437B8DB3B41FE0E5ACEAF497FD4A0AF /* Products */ = { + isa = PBXGroup; + children = ( + 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */, + B477F169CB917A9F07ABB3C6B0ED46BE /* Anchorage.framework */, + 11AF731E4071DCD5E34B4CA294302B92 /* AppCenterDistributeResources.bundle */, + 33A4868B2CB72C28A43C9793FA150418 /* BonMot.framework */, + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */, + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */, + 5B654B4B042BA7DC93766943A643E42B /* FirebaseMessaging.framework */, + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */, + E8EE7F078656FABB8F6821D10FF994BB /* KeychainAccess.framework */, + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */, + 17E33041B314FA837A3CAEB9DF3CDE9F /* OHHTTPStubs.framework */, + 3C43A20C9129EB73F5BA4F3C40D9A27A /* Pods_{{ cookiecutter.project_name | replace(' ', '') }}.framework */, + 8B0B7D7F03E7C5408A9FEDE21398424D /* Pods_{{ cookiecutter.project_name | replace(' ', '') }}_{{ cookiecutter.project_name | replace(' ', '') }}Tests.framework */, + 029DC932573FD3CFF2AB08725C770343 /* Pods_Services.framework */, + C2105C94812B6214B154F54DCEDB72AC /* Protobuf.framework */, + A787CDE742CEB6FDF5F73F556D790691 /* SimulatorStatusMagic.framework */, + F7696B90A3B3D1C34C7E852254DD74F1 /* Swiftilities.framework */, + ); + name = Products; + sourceTree = ""; + }; + C59A82E1D6A01A9AEE70D0221E9593F7 /* Instabug */ = { + isa = PBXGroup; + children = ( + DE16395C09D232F30431F9810A0872D2 /* IBGBugReporting.h */, + 5EB40E5CF6D5BE4269E687E374531BA9 /* IBGChats.h */, + 1B6C4D3F28F3CBA7CF305CB592F85E32 /* IBGCrashReporting.h */, + 82350E48404736EC458CE6073EFD26C3 /* IBGFeatureRequests.h */, + 71A5AB122315590AD0A59A0DA56F3DA9 /* IBGLog.h */, + 488D7FCF0C4C3011E9931E973C97CB62 /* IBGNetworkLogger.h */, + CB5E05211C1CC74484FAD2D8B97F2437 /* IBGReplies.h */, + D3CAB6FE3C8CDCA5DBD77435EA5A937D /* IBGReport.h */, + A0540CA217C994053589CECC283EFEE1 /* IBGSurvey.h */, + 4FC53E880281E6082EF5E821D70B924D /* IBGSurveys.h */, + 179351A254DB884FEB79BA11A69753BF /* IBGTypes.h */, + 79B0EA6DE3F64B8EB2ED292B450C2FBB /* Instabug.h */, + ED06C07D733F97DE5A5F19FEBD086CF5 /* InstabugCore.h */, + 0B7FB0654F18D64FE0D7A2EAAC682B23 /* UIView+Instabug.h */, + E60F7906D799BBA108A0DAB4D2153C5B /* Frameworks */, + 61E1FBD62BF31EF9C5C6FCF8C2475554 /* Support Files */, + ); + name = Instabug; + path = Instabug; + sourceTree = ""; + }; + CA9B7F5CACE5568B170B81CEF9190D72 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 7F7F3C5E8428F9EC082EB77C8B6C0743 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }} */, + 8BDFEEE65FACF169A2EB85AE06AD1146 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests */, + 7A06EBF1D3AE62AED0DC085715332089 /* Pods-Services */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + CEC3374FD169D13C3E074C43021D181B /* NSData+zlib */ = { + isa = PBXGroup; + children = ( + 966E61D7CDD4B8F269B4C52F6C9D4E6F /* GULNSData+zlib.h */, + E73E251E3CF96E1495BE3EC085526D94 /* GULNSData+zlib.m */, + ); + name = "NSData+zlib"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 8275CCB4E8732497B1021FCBC240F3C2 /* Frameworks */, + 8D527B9C3DE0F3C4790F2C72704D59DC /* Pods */, + C437B8DB3B41FE0E5ACEAF497FD4A0AF /* Products */, + CA9B7F5CACE5568B170B81CEF9190D72 /* Targets Support Files */, + ); + sourceTree = ""; + }; + D5A1FC161D50AE992042E65485320E60 /* FirebaseCore */ = { + isa = PBXGroup; + children = ( + 1A2C2A90AABD3780C5969C4B208AF34F /* FIRAnalyticsConfiguration.h */, + 5FBA28A120B7A31F4D7E17E23F881916 /* FIRAnalyticsConfiguration.m */, + F6D1E9800DF9216163D243A25E5A7E22 /* FIRApp.h */, + 137550D164A3DC3110CE137D5BC383BE /* FIRApp.m */, + F0821896A90AE916F84B3E580249644D /* FIRAppAssociationRegistration.h */, + 0245E1DD96C5A71E0976E257585FB875 /* FIRAppAssociationRegistration.m */, + E893CE5D8A792CBF4C835E33C903AB37 /* FIRAppInternal.h */, + A9F6CAA436B21A9F893735228C041394 /* FIRBundleUtil.h */, + 367F00084F5782810F06E3AE60988239 /* FIRBundleUtil.m */, + CE3DE9896DF364A9A8E70FBF3411CAAD /* FIRComponent.h */, + 900494C92D1BC8DD44B41A1E185446A2 /* FIRComponent.m */, + 72AA8EF20A9E0ED207B17A82A67948D7 /* FIRComponentContainer.h */, + 5CF43C772DF570A45DC9831438386FF8 /* FIRComponentContainer.m */, + 4E4A10F6099BBA9290EDF1F50E4E1E06 /* FIRComponentContainerInternal.h */, + 994790A4BDFB35C5FEEEB4B16ACD0073 /* FIRComponentType.h */, + 990D5BCA382BD9D9D2C3C1E291F2B135 /* FIRComponentType.m */, + B5391DB5CF7FE004619D4F1920521EA2 /* FIRConfiguration.h */, + 9B7024F62947EF6E2C6FB6CD5B34E2ED /* FIRConfiguration.m */, + 106E91C219A27E966E2F6168D1D7F3CA /* FIRConfigurationInternal.h */, + 3D735903962EFF3FC6A7517312F923CA /* FIRDependency.h */, + FF710E85F020077130E558211B5B8D8A /* FIRDependency.m */, + CEC8FF8EB54F243F318CF7B7F16F7278 /* FirebaseCore.h */, + 86B9F61513C3569FB8F5F80587BD0802 /* FIRErrorCode.h */, + 78082F41A23883083EE4061BFC18A4D3 /* FIRErrors.h */, + AC024504A5C4B47AE13B434EA483D427 /* FIRErrors.m */, + 4B4AA562F866C56D8D686538218F79EA /* FIRLibrary.h */, + 5C494458D65556B106276B45877C5407 /* FIRLogger.h */, + 7902953F39F914B13DAD07D6C494973D /* FIRLogger.m */, + B02CBEEE2EAAE48F5C59A0748E149382 /* FIRLoggerLevel.h */, + D2B4AA2B21255F7A6AA09F0E059321BF /* FIROptions.h */, + 97EFF3947D869F0FC7D7D08A1B3B0A6E /* FIROptions.m */, + 4FC123B26387B1A38B1AAB531554C64E /* FIROptionsInternal.h */, + D436B935FFA96DDB042376CB5C11E29E /* FIRVersion.h */, + 772EBD4355380FAEEEE486F50277CA1F /* FIRVersion.m */, + 662F353757E6B7E31DA01A696E1A2E2C /* Support Files */, + ); + name = FirebaseCore; + path = FirebaseCore; + sourceTree = ""; + }; + E09CF835A9CE9B38B033D04BE754B8C6 /* LicenseFormatter */ = { + isa = PBXGroup; + children = ( + 1B77C6FBEB46883FCDBBBF0333AAA959 /* LicenseFormatter.swift */, + ); + name = LicenseFormatter; + sourceTree = ""; + }; + E101FC07342B02BB434763AB5503FDF0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 45FA4D2E7421B8D456A7B6F36884B54B /* GoogleAppMeasurement.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E60F7906D799BBA108A0DAB4D2153C5B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0FF31F44B7641D6494DCF4BD9B15D1D2 /* Instabug.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E81AD734C1E0D7D9E60EBB121AB226B1 /* Support Files */ = { + isa = PBXGroup; + children = ( + FCCFBDA197465FE364E665276C2A88CA /* FirebaseInstanceID.modulemap */, + A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */, + 8FD395C6B080D05AA0E9B521C84DE95C /* FirebaseInstanceID-dummy.m */, + 72C7D6029AC9F37ABD0F2A4F076D6125 /* FirebaseInstanceID-Info.plist */, + A86060F6B97532F283FE392A2B356F3F /* FirebaseInstanceID-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstanceID"; + sourceTree = ""; + }; + E97757579390FAE0C029F4AB98E7459C /* Support Files */ = { + isa = PBXGroup; + children = ( + E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Fabric"; + sourceTree = ""; + }; + ECC016BE841E69D8F7164C18E603AB7D /* Support Files */ = { + isa = PBXGroup; + children = ( + FD757FD2EC6B3B19A20C755C1B166C5C /* Anchorage.modulemap */, + 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */, + 569222352AED8AA275E1295F319C179D /* Anchorage-dummy.m */, + 86773016D7292DB1077AB6ED22B7CAE1 /* Anchorage-Info.plist */, + 4EC0877FA9D2F6B5649644D06256D79A /* Anchorage-prefix.pch */, + 031FC7BA2605BE0368D9692DBDC15D81 /* Anchorage-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Anchorage"; + sourceTree = ""; + }; + F04C2CDACCB32D83923281C298391F52 /* Logging */ = { + isa = PBXGroup; + children = ( + 7A99BF2E906BA57B9D716EC2F28447CF /* Log.swift */, + ); + name = Logging; + sourceTree = ""; + }; + F207982E6DE213CFE74F9EF7393F63A1 /* RootViewController */ = { + isa = PBXGroup; + children = ( + DD6A6E8BEA17526E69B7E7C440D290E2 /* UIWindow+RootViewController.swift */, + ); + name = RootViewController; + sourceTree = ""; + }; + F52DE65EA93C92C1F1F94D5B0BC29E6A /* Reachability */ = { + isa = PBXGroup; + children = ( + 14E3AE25C553C268ECABA7BA60383152 /* GULReachabilityChecker.h */, + B2E98DDB0684CD0EED258207851A2A13 /* GULReachabilityChecker.m */, + EFBAAB841881AAAD3B071BA31361B288 /* GULReachabilityChecker+Internal.h */, + 73B6B0B82C4B090FD5CCE3E4B3185607 /* GULReachabilityMessageCode.h */, + ); + name = Reachability; + sourceTree = ""; + }; + F7114582B168E212D19780C5CCFBEC19 /* Support Files */ = { + isa = PBXGroup; + children = ( + 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalytics"; + sourceTree = ""; + }; + FBB07FC05F11C073D5B30FFFF4FB1787 /* decode */ = { + isa = PBXGroup; + children = ( + ); + name = decode; + sourceTree = ""; + }; + FC97710BA2AAAA3C677BBC481F15EDAE /* Views */ = { + isa = PBXGroup; + children = ( + AD145FCE40536EC56F550EF22AE3A2B3 /* GradientView.swift */, + 59995D0C9E351E7C567DF118C940304B /* PlaceholderTextView.swift */, + 0ED0360339FFD929C312164430AECEF5 /* Protocols.swift */, + 4F7DFC7F79DE29AD380D6C23EF374F66 /* TailoredSwiftTextView.swift */, + 2765A7D6EF27B9AB42D6279A14D1669A /* UITextView+Extensions.swift */, + ); + name = Views; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 03049833CA31385BB30D4A6974B16E79 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C9D3548AB6302BFF4E52AB249E9B2FA /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0431DD53A227464D09A063063050448A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B501012C85EBF16411A4B9CF856A3044 /* BonMot-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1E515CC83C1A6C69B90E75E32C99344A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C289B85A33500EE2453F08CE5D0DB7EC /* GoogleUtilities-umbrella.h in Headers */, + B075936A698C95B193BF870AF0C5DE9C /* GULAppDelegateSwizzler.h in Headers */, + 05A179D28D1AEFB2994F50DF04732ECC /* GULAppDelegateSwizzler_Private.h in Headers */, + B070DBBE6F946A656405E140E975A211 /* GULAppEnvironmentUtil.h in Headers */, + 9B713E8E0EFE0EA70A995827E5394683 /* GULLogger.h in Headers */, + 414165239CE300A52CEB93BE48E70607 /* GULLoggerCodes.h in Headers */, + BC256D583C7221D6FE3DC13F08C02FEA /* GULLoggerLevel.h in Headers */, + 63E56D00C55C0A10C4B75F082AF81B6E /* GULMutableDictionary.h in Headers */, + 8D8C7DD544D90026F85550B2CC95CBD5 /* GULNetwork.h in Headers */, + 2E5638B808692AE3B2213A66E618B793 /* GULNetworkConstants.h in Headers */, + 756BA8556D315CD499501E923700528F /* GULNetworkLoggerProtocol.h in Headers */, + A818814179D868596CE5F1BC13302BB3 /* GULNetworkMessageCode.h in Headers */, + 92716A0085066BCCB43369069E76403A /* GULNetworkURLSession.h in Headers */, + 6FA68690945C1A9D56524BE6EEB1B23F /* GULNSData+zlib.h in Headers */, + 0C0BF1B04934ADA346E62844B9324E2A /* GULOriginalIMPConvenienceMacros.h in Headers */, + B4B77955EC2C522E041EBA397F87FE65 /* GULReachabilityChecker+Internal.h in Headers */, + 8FBBD77BDF34DDAA858E757318F1FAC5 /* GULReachabilityChecker.h in Headers */, + AA2AA7707B86A60F4E9CCA3E1BE504CA /* GULReachabilityMessageCode.h in Headers */, + 816CD4237A652BDEADE317F1DD341A0E /* GULSwizzler.h in Headers */, + CBBFF56D23D20E974E5D8DF04EF3637B /* GULUserDefaults.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 31917A544DEDF75840A86242DA086C54 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 09BBB2DFD0CCA4F842ED217E1ADE6141 /* nanopb-umbrella.h in Headers */, + 05EBDF811901C96CB4A388C239C95E5C /* pb.h in Headers */, + 67D67C17FCCB5F83FF620BD048630184 /* pb_common.h in Headers */, + CA260A0E0878CEE776DE12492DF46949 /* pb_decode.h in Headers */, + DFADB7B9266D1032D5BF21F2F1D02D96 /* pb_encode.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51047DA7E35C429BC28F0F43004BD8C2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FC6AFA3387CA425C566B007F0EA9B9A9 /* FirebaseMessaging-umbrella.h in Headers */, + 988E2668D29D51B8304BC24235BA15B6 /* FirebaseMessaging.h in Headers */, + 9811AF1663228E41A0F9116F3FDAB4D3 /* FirebaseMessaging.h in Headers */, + 93B158CFAE0146108F8D3DF1F5DF2FEE /* FIRMessaging.h in Headers */, + 059037195C74C676763DE7253C64DCAC /* FIRMessaging_Private.h in Headers */, + 9C27962A6C09FD001BE83B3873C40856 /* FIRMessagingAnalytics.h in Headers */, + 03EF25966CA31FFBC31B8044BBDB7C78 /* FIRMessagingCheckinService.h in Headers */, + 66F6BC937ACA5E47AF09DB8ABB6D7645 /* FIRMessagingClient.h in Headers */, + 2BC2424190D3B6288B51C3DAAC70FE0D /* FIRMessagingCodedInputStream.h in Headers */, + 5066B89BFDEBC3087F0077E0E19D605A /* FIRMessagingConnection.h in Headers */, + D46809D86D5BB4EBB9AA10F29979A860 /* FIRMessagingConstants.h in Headers */, + 6AC487E61CBA42325EAEE431BBCCA6C0 /* FIRMessagingContextManagerService.h in Headers */, + 6AA8F0D7888C5B32C0D72865D646F69B /* FIRMessagingDataMessageManager.h in Headers */, + 94F0EFD969D064F5D663A6EE835D4516 /* FIRMessagingDefines.h in Headers */, + 989554E915C48AB0868348384AE545C8 /* FIRMessagingDelayedMessageQueue.h in Headers */, + 7EAB3629AFCDDB950B9A4C610588D97A /* FIRMessagingExtensionHelper.h in Headers */, + 27A8DB4EE609E1FABE7EA7835B6FF28B /* FIRMessagingInternalUtilities.h in Headers */, + 8D769B1E75C52E3BFAC64ABA8CA438FE /* FIRMessagingLogger.h in Headers */, + E98CBA7CFCF3D96C5B50770A4D3517B5 /* FIRMessagingPacketQueue.h in Headers */, + 220FF13741674D3D3CF5BAD8DFCE5E92 /* FIRMessagingPendingTopicsList.h in Headers */, + BA0C33AE7563904D128CB643510CCBE3 /* FIRMessagingPersistentSyncMessage.h in Headers */, + 17CA76C0BACF692C96BD0A789D76C08D /* FIRMessagingPubSub.h in Headers */, + 8A8D4BB3B21FE7CECDAA6908E6886531 /* FIRMessagingPubSubRegistrar.h in Headers */, + B8C5257CFBE55442EECF051DF82E729B /* FIRMessagingReceiver.h in Headers */, + 96468709B156DCAC50DABCA9CB197F21 /* FIRMessagingRegistrar.h in Headers */, + E985433DB346442DDCB5F6E16CE7D280 /* FIRMessagingRemoteNotificationsProxy.h in Headers */, + 2AA0A2B7267E8E75525D003D9A96E6ED /* FIRMessagingRmq2PersistentStore.h in Headers */, + 9C24AF3D249563A26F59EDFBA4C7773A /* FIRMessagingRmqManager.h in Headers */, + 0D110E5F8DB3A38046128C3AD51467AC /* FIRMessagingSecureSocket.h in Headers */, + A18D4637F3EB0E9D08ABB14CE34737CF /* FIRMessagingSyncMessageManager.h in Headers */, + C9157A5A1365EB4A1D49EC2E8619E4F7 /* FIRMessagingTopicOperation.h in Headers */, + 23A2410F3C4DE63B77014C9DE596F51C /* FIRMessagingTopicsCommon.h in Headers */, + 71775A89A3802A1BA58BF1BB41DDD9A1 /* FIRMessagingUtilities.h in Headers */, + C19BF82AAEAC7AD417C728F4C00B58CE /* FIRMessagingVersionUtilities.h in Headers */, + 021DB76932CE50DD90304FEBFCA8BE77 /* FIRMMessageCode.h in Headers */, + EF6D8F4A474E5287ABFAE4449F45C827 /* GtalkCore.pbobjc.h in Headers */, + F751BBA11B2C9DB683D3FAC54D1B54EC /* GtalkExtensions.pbobjc.h in Headers */, + BBE95066A8DC1C8D8CC907000D70541A /* NSDictionary+FIRMessaging.h in Headers */, + C329C3A3A838C4AD86611F67A10BFEAF /* NSError+FIRMessaging.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5ACB9E7F9554486F77804743DD21C9FF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 307995802DBDCAE24CD40AA467DFDD9D /* Swiftilities-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 70969CE00B19E6C2CA2868F9FA0AE35C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A3492135E0BFF1F6BE2DB3BCB52907C7 /* KeychainAccess-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8823DEEADB239F8D563D480A7126611F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A81ADD3C0C26EEFD1409AD35142E0AF /* Pods-Services-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8F23573CF45EC7A6EE1BEBC0F3BA4606 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D448F684FAE5EF02A10E467A097B2B8E /* Any.pbobjc.h in Headers */, + D86369D98CDF2CD116CBC4B66B089CEB /* Api.pbobjc.h in Headers */, + 807B6E3FF4C4A97577F4D5EDDDD49ECC /* Duration.pbobjc.h in Headers */, + 7C9F9297EAC2E0A5302B50564B575B0A /* Empty.pbobjc.h in Headers */, + 4BAB4E1DF3D4D6AF88A8508E3A2F09A8 /* FieldMask.pbobjc.h in Headers */, + 68333497E7CEB0B383B8F14BF0B0B6BE /* GPBArray.h in Headers */, + 93FEDE6C16994FA82F27CC56168013FF /* GPBArray_PackagePrivate.h in Headers */, + 0AAA11C4CFB301157A24BF56A7C1ED7E /* GPBBootstrap.h in Headers */, + CE60B4B85D17A08CA721EEE416CD1C83 /* GPBCodedInputStream.h in Headers */, + 488F9DFC7A23F9EA87DA50076865695A /* GPBCodedInputStream_PackagePrivate.h in Headers */, + B9AFBB66C67E71F0BFDD0DE5687C9CBC /* GPBCodedOutputStream.h in Headers */, + 1BE02480F93F6FEF703BC98F779A8FBE /* GPBCodedOutputStream_PackagePrivate.h in Headers */, + 50A0609DC011B95A498F342D6A496297 /* GPBDescriptor.h in Headers */, + BE2C9A27C741D9C0773B4037E0D68B57 /* GPBDescriptor_PackagePrivate.h in Headers */, + 365196A7B4EE1C83C432D345AA839C88 /* GPBDictionary.h in Headers */, + B6D9136FE482A5716B99CAE6FF7545F4 /* GPBDictionary_PackagePrivate.h in Headers */, + B734B64212F2A039FCAC85F14608AACA /* GPBExtensionInternals.h in Headers */, + F2C4A6F7AC480DEFAE6217C46C05E974 /* GPBExtensionRegistry.h in Headers */, + 890D4B46D1BE3870CA15607A41327FAF /* GPBMessage.h in Headers */, + 643932FF6C60A7B50E69281BEC283DCC /* GPBMessage_PackagePrivate.h in Headers */, + EA4C0FEE83B95FA4CBD6A1C7A1041CCA /* GPBProtocolBuffers.h in Headers */, + 3F318A17631E107812E804B75FFB7FA6 /* GPBProtocolBuffers_RuntimeSupport.h in Headers */, + E75E3A02BC9CCB56D1671F7FDCB1D543 /* GPBRootObject.h in Headers */, + 1B9376E58DD7B9226E8EBA79391DF110 /* GPBRootObject_PackagePrivate.h in Headers */, + 5D6901CB7E479AF1C5F8A340BABB727A /* GPBRuntimeTypes.h in Headers */, + 93F97DB70699CDB8C433DEB03991621E /* GPBUnknownField.h in Headers */, + 36D435F6F2D69F1A933BAE5D27B0EF85 /* GPBUnknownField_PackagePrivate.h in Headers */, + 35E679A58A9EF087D8AAFB484914B64E /* GPBUnknownFieldSet.h in Headers */, + 8060AA86BCD21633E21A8DA29FD56D07 /* GPBUnknownFieldSet_PackagePrivate.h in Headers */, + 1E84D4A521B67526F319DBFFCE9486B7 /* GPBUtilities.h in Headers */, + 8C435621C8561A336FCB112215CE7F06 /* GPBUtilities_PackagePrivate.h in Headers */, + 33108ECB357D1206B36ED2F85AC12269 /* GPBWellKnownTypes.h in Headers */, + 760970F7357E9ECCDFF141830982057F /* GPBWireFormat.h in Headers */, + 74CFDB81D12600FF74EAF4FE27423E07 /* Protobuf-umbrella.h in Headers */, + 5F12EFB41C6F7259375BF3E842CE980A /* SourceContext.pbobjc.h in Headers */, + 7F665E687CD8C311206F990CD0DA7418 /* Struct.pbobjc.h in Headers */, + FF1D8B1CA0865B7484F0874C6517D3CD /* Timestamp.pbobjc.h in Headers */, + 1A0898925095DFC70512C1A28BD9F587 /* Type.pbobjc.h in Headers */, + BF4C76B8E0C15E7C2A4762EBB84872F0 /* Wrappers.pbobjc.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B8851F99376F0F8A8D9CEE158F4A4DF5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6A9ACBEB61712282B87B0A3090045B36 /* FirebaseInstanceID-umbrella.h in Headers */, + A7A6BF0C62BC3FC2F757468C317099EE /* FirebaseInstanceID.h in Headers */, + 9895E36F7164AEA6EFADE585598C4B9F /* FIRIMessageCode.h in Headers */, + BEC7476DE1CF263A31FA893D2B2A2E70 /* FIRInstanceID+Private.h in Headers */, + 917E9C7AF939B0FFD3C026BB4EAC73DF /* FIRInstanceID.h in Headers */, + F5A597E46D8296D2C414626E7F99C0EF /* FIRInstanceID_Private.h in Headers */, + 9243AFCD79CC422AC3AE16E6CB0C262D /* FIRInstanceIDAPNSInfo.h in Headers */, + 83CA30B037DEB0527448F9C54F396B2E /* FIRInstanceIDAuthKeyChain.h in Headers */, + 28501C3F19644C8E8888E168B5163A2B /* FIRInstanceIDAuthService.h in Headers */, + 949E82C19D7A44BEA21AE96476C2E533 /* FIRInstanceIDBackupExcludedPlist.h in Headers */, + F9A8B355EC256F8B149021EB7C0F8998 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */, + A3A7C1C339F3BDCF7DAE115107D4FC89 /* FIRInstanceIDCheckinPreferences.h in Headers */, + CE8F8AFEE45337F90EBA0EB35A82939E /* FIRInstanceIDCheckinPreferences_Private.h in Headers */, + 130BCF85E0BDD69B046F3000354BA0B1 /* FIRInstanceIDCheckinService.h in Headers */, + 07004386F300F8DD87A2D100C010521B /* FIRInstanceIDCheckinStore.h in Headers */, + 409D2E6AB1246D3B41550EC6F8B68695 /* FIRInstanceIDCombinedHandler.h in Headers */, + 6A5EF7BFD9E1F744141F8FADA93CC40C /* FIRInstanceIDConstants.h in Headers */, + E88203FD8E2B01EB71219367D94608D0 /* FIRInstanceIDDefines.h in Headers */, + 26939CAD52ABAD1A55806F176550DA26 /* FIRInstanceIDKeychain.h in Headers */, + 49D4D750DDF02487C8AA4B26B1D85942 /* FIRInstanceIDKeyPair.h in Headers */, + B39604A46A4903C262D18E317F1E6C6C /* FIRInstanceIDKeyPairStore.h in Headers */, + 49894777E431600670C3413CFD08CBAC /* FIRInstanceIDKeyPairUtilities.h in Headers */, + A5F185E6FD5C3BBCF46BF62774965E31 /* FIRInstanceIDLogger.h in Headers */, + F5DC2F62DE6E7D1D2166347768660F62 /* FIRInstanceIDStore.h in Headers */, + E1797B933E4A716E831F34EFC24F2A18 /* FIRInstanceIDStringEncoding.h in Headers */, + BFD1F6C176B28F48CCF2BA6577A6C170 /* FIRInstanceIDTokenDeleteOperation.h in Headers */, + 7D9390DFB58EAEF71DA1CE4E5F4AA98D /* FIRInstanceIDTokenFetchOperation.h in Headers */, + 2B088D091DA7DA702E17C2022DFE2D14 /* FIRInstanceIDTokenInfo.h in Headers */, + 8DB74A47E65D6DF7F9632EA8709028C7 /* FIRInstanceIDTokenManager.h in Headers */, + 837BDD2C7B095A5B3544B3B632ADA738 /* FIRInstanceIDTokenOperation+Private.h in Headers */, + E86C0147FE8704C88040B0AFEF4E7648 /* FIRInstanceIDTokenOperation.h in Headers */, + AAA60349DF99530BA4F476C8D9DF2AC7 /* FIRInstanceIDTokenStore.h in Headers */, + DC5DA57E4485C2FC85FDF53428C747DF /* FIRInstanceIDURLQueryItem.h in Headers */, + 1168EAF844C5167A969F992B39124E95 /* FIRInstanceIDUtilities.h in Headers */, + 93FE3279105620965FABBD2F6D30ADB1 /* FIRInstanceIDVersionUtilities.h in Headers */, + EFE7887C3624E7E6BA06AECB489778FE /* NSError+FIRInstanceID.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BC611EA94FEA3BF8D61D449B9247327D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F7F70BA374635820D060762A15931D3 /* SDStatusBarManager.h in Headers */, + 3B17099ADDBF828A11994064917317EC /* SDStatusBarOverrider.h in Headers */, + A142ABBB6E27723CB76393007499BBCC /* SDStatusBarOverriderPost10_0.h in Headers */, + E2E71589715B273DE6163D5FB435592C /* SDStatusBarOverriderPost10_3.h in Headers */, + 1BCC66B692E9EDE5C903B4469B4BCE57 /* SDStatusBarOverriderPost11_0.h in Headers */, + 9DD886828EFFBBDB2439ED4B11CE081B /* SDStatusBarOverriderPost12_0.h in Headers */, + B45A8A82A0FD4C548C6DB743E8095E86 /* SDStatusBarOverriderPost8_3.h in Headers */, + 4FC8500AC1BDC6610782C5C287EAFB46 /* SDStatusBarOverriderPost9_0.h in Headers */, + 9335522C7018277CE54C18E182A5A1F4 /* SDStatusBarOverriderPost9_3.h in Headers */, + CA601EE9EDA47E65195D3BF43930A270 /* SDStatusBarOverriderPre8_3.h in Headers */, + 66EF408EFC3D695477CAAA86191FF5A2 /* SimulatorStatusMagic-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CD7D21AA0812F3958596A40163651653 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D9D8875B70BCDA90E099D5BA8A43A802 /* Compatibility.h in Headers */, + 6239F27D209AFEA6F20DC38D2EA8BF53 /* NSURLRequest+HTTPBodyTesting.h in Headers */, + 8494ADF872F49EA36C4844F0298DD498 /* OHHTTPStubs-umbrella.h in Headers */, + 1011297752537301D863BE2D4B01E43A /* OHHTTPStubs.h in Headers */, + C2158E550AEB96660AD13D089D75543B /* OHHTTPStubsMethodSwizzling.h in Headers */, + CA4CD125AEC29FD189D003762B57494A /* OHHTTPStubsResponse+JSON.h in Headers */, + 9E2AC1BC432B98F9B748D05D7B488CB0 /* OHHTTPStubsResponse.h in Headers */, + 49FF7B5676B99AC5BC66CD274572D5F8 /* OHPathHelpers.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5283B3D873288E1A36B8278880117D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F6F184A43AABC119977DF12AD2ED2053 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E04484D640E829A11EDEA568EB57DB7F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 94E0EEAC1123DEFF7625B88F0E71E3E9 /* FIRAnalyticsConfiguration.h in Headers */, + 77399B95DEEE5E953DF7BADB4B7139D7 /* FIRApp.h in Headers */, + DA5908E1CF98667FAE1CBEC76D355CA4 /* FIRAppAssociationRegistration.h in Headers */, + 00615AAC8F76F88D5B261CDBAFFC42CC /* FIRAppInternal.h in Headers */, + F9B80E71A9F0D909B1F73CCD753CF53B /* FIRBundleUtil.h in Headers */, + D4EB284204E633D9175B0D5D850EB0EE /* FIRComponent.h in Headers */, + 2DF1DEC33EB066E5581440CD6998386C /* FIRComponentContainer.h in Headers */, + 1C202B0C77A04F7D0E65F399808DBB11 /* FIRComponentContainerInternal.h in Headers */, + 360522FAF4C83FF5BB33C984F4D293B5 /* FIRComponentType.h in Headers */, + 2A06EC8F16F9A176A6E8969AEFCF557E /* FIRConfiguration.h in Headers */, + 4C4E5BAB5F6CEF8DC0184E7045DE6319 /* FIRConfigurationInternal.h in Headers */, + F5770C14010A6EA5DDF6D28111858B75 /* FIRDependency.h in Headers */, + 72E64E250ECE3FED90F8E229980CD42F /* FirebaseCore-umbrella.h in Headers */, + C8A5AA38971136EED1E4BC61205A591B /* FirebaseCore.h in Headers */, + 2B6BD33D9BA13D63533BF7A016186C63 /* FIRErrorCode.h in Headers */, + 23B15157951EFE8223491E517FB38492 /* FIRErrors.h in Headers */, + 55F7228A18EA4ADE7388939284DC1828 /* FIRLibrary.h in Headers */, + 29D8A0E1833835AE95BB8D68783E01D3 /* FIRLogger.h in Headers */, + BEF4756AFAB837E4497F73F05DEDEECC /* FIRLoggerLevel.h in Headers */, + 09F7DF5894417D5165C5B1873E46B448 /* FIROptions.h in Headers */, + 0FD7700F7E5A81A21AEB14558CCCD67B /* FIROptionsInternal.h in Headers */, + 398916FB2E858FCF90B787DF390F0646 /* FIRVersion.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1271C58F3B4DED1AC9FAFC325A29CAF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6C654A56978C6D1886240834580D72C3 /* Alamofire-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E5F63544CC885EFB40146133912498EE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A0DD808CD41CE6A758A3C64289598B2F /* Anchorage-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */ = { + isa = PBXNativeTarget; + buildConfigurationList = DEA17664DA1352A9AF015846F7DC4098 /* Build configuration list for PBXNativeTarget "FirebaseCore" */; + buildPhases = ( + E04484D640E829A11EDEA568EB57DB7F /* Headers */, + 8AD0FEC519E2F25A92EFA4A40E97C225 /* Sources */, + 74C2CDA0B2C1E3C0ACC15492B3B38619 /* Frameworks */, + 3D6135916B343D7E548A3F64DBFE6EF8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C4D6DC5312308B518D11684361884474 /* PBXTargetDependency */, + ); + name = FirebaseCore; + productName = FirebaseCore; + productReference = E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 44E83D2F8D3A4919879F6D9FA69CBC61 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }} */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4964BEA93FE393CBB81F0EB03B4B3C81 /* Build configuration list for PBXNativeTarget "Pods-{{ cookiecutter.project_name | replace(' ', '') }}" */; + buildPhases = ( + DA5283B3D873288E1A36B8278880117D /* Headers */, + C5EDC2EFB9F2A36C846524DD554C6A16 /* Sources */, + 726B5C2231D21F110E448BFD5292F6A1 /* Frameworks */, + 88B8A813538905511C304057DC4AC323 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C5E8A7AE78E64723705A8C4F39294C2 /* PBXTargetDependency */, + F0793E63BFABF823AEB6F71A3674DAE1 /* PBXTargetDependency */, + 027A71A52AB8D3D436ECDC9CB733277E /* PBXTargetDependency */, + 76368B6D12BB326EEFA9898C11C103BF /* PBXTargetDependency */, + 790A3D878446B70A5A20256D674AB5E1 /* PBXTargetDependency */, + 72C383DDA0C3B15B45C1BBE8168E7C32 /* PBXTargetDependency */, + 83F2C143D8BEF77B7C4759F0CAFB4E62 /* PBXTargetDependency */, + 9F9E6213111F42F60CF9E3049030C0EC /* PBXTargetDependency */, + FE817F57A0DB193392689548BF3A3052 /* PBXTargetDependency */, + A8FE2505F0526DA98700BDEF778002CA /* PBXTargetDependency */, + 57A98EA8D303A644FA7B50E4295B8171 /* PBXTargetDependency */, + 80661FD0776FF5CE9CEA1E2D72C1B901 /* PBXTargetDependency */, + 5CE6985057CE4B265103CF4F42193E36 /* PBXTargetDependency */, + D26A457C36225DE41C7BB4FD7A7FF254 /* PBXTargetDependency */, + 5C27114E1234A898AE9167984987A6BB /* PBXTargetDependency */, + E4A173EB136AA75485C7DD75F12B1475 /* PBXTargetDependency */, + 517C4D4310C32500D8D3C4AFB217A87A /* PBXTargetDependency */, + 34CC4B4491776D9C45A351FBC15D65D4 /* PBXTargetDependency */, + FE3F8C74A60E5614770271527A3085D9 /* PBXTargetDependency */, + D0405CD352F9BA331E0835E76731E1D5 /* PBXTargetDependency */, + 5F429333A5E8F5B0843B8383C878CEDD /* PBXTargetDependency */, + F7AB0C563506FE1FE6520F4C7180C61E /* PBXTargetDependency */, + FEB053648A54BC05E6A6BD49CB6EFFB8 /* PBXTargetDependency */, + ); + name = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}"; + productName = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}"; + productReference = 3C43A20C9129EB73F5BA4F3C40D9A27A /* Pods_{{ cookiecutter.project_name | replace(' ', '') }}.framework */; + productType = "com.apple.product-type.framework"; + }; + 4607A9D579EE69C57F52971930107170 /* Anchorage */ = { + isa = PBXNativeTarget; + buildConfigurationList = D99A31EFD5DABE8C08BD3F146933A31D /* Build configuration list for PBXNativeTarget "Anchorage" */; + buildPhases = ( + E5F63544CC885EFB40146133912498EE /* Headers */, + B171C95BD079223B02E20B54DAC07B3F /* Sources */, + 32D9EDE9ED3871400CB94EF9184C0D6D /* Frameworks */, + C2335386EAEE724F85DA53C2B57D58AC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Anchorage; + productName = Anchorage; + productReference = B477F169CB917A9F07ABB3C6B0ED46BE /* Anchorage.framework */; + productType = "com.apple.product-type.framework"; + }; + 470FE31978DC918618A329D8B55C85FF /* Protobuf */ = { + isa = PBXNativeTarget; + buildConfigurationList = 994CC284732864C1FB83DEFEECB2939B /* Build configuration list for PBXNativeTarget "Protobuf" */; + buildPhases = ( + 8F23573CF45EC7A6EE1BEBC0F3BA4606 /* Headers */, + 72B8E25E992B707A92C7C56A5B4D1DD0 /* Sources */, + 07E3F9AF597FEC90D3D85283E3E5DA0A /* Frameworks */, + E1E3FEBB4ED67C9E1AF276D80B54F7BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Protobuf; + productName = Protobuf; + productReference = C2105C94812B6214B154F54DCEDB72AC /* Protobuf.framework */; + productType = "com.apple.product-type.framework"; + }; + 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */ = { + isa = PBXNativeTarget; + buildConfigurationList = EBAF0176DA76634D02397BD80DC087AD /* Build configuration list for PBXNativeTarget "BonMot" */; + buildPhases = ( + 0431DD53A227464D09A063063050448A /* Headers */, + 29333CABA17205542DF156993C524977 /* Sources */, + 96338CCDB13BC8D010311E35BC765F14 /* Frameworks */, + 64B88C84E52D7233869509EAEC6387F2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BonMot; + productName = BonMot; + productReference = 33A4868B2CB72C28A43C9793FA150418 /* BonMot.framework */; + productType = "com.apple.product-type.framework"; + }; + 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7C6BA1361CF9FA39E02D40A29E2613E3 /* Build configuration list for PBXNativeTarget "FirebaseMessaging" */; + buildPhases = ( + 51047DA7E35C429BC28F0F43004BD8C2 /* Headers */, + ECAA69750FA4F99D92214CCBCCDAF45E /* Sources */, + 255C7B5ED5FE9184B51E5BED246FA3DD /* Frameworks */, + 1963B15BA5DDF39E925E404B1B5C69D8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 509CCF144E767C197328128D373A1367 /* PBXTargetDependency */, + F9A75F4BC4D33D1F83CBE160AE2D088A /* PBXTargetDependency */, + 21126DE93342F0CFC72E8B0BFF74B7C2 /* PBXTargetDependency */, + A3560B04C6C7550C49D3509E4F985634 /* PBXTargetDependency */, + 912865061B33024F53771995A880334E /* PBXTargetDependency */, + ); + name = FirebaseMessaging; + productName = FirebaseMessaging; + productReference = 5B654B4B042BA7DC93766943A643E42B /* FirebaseMessaging.framework */; + productType = "com.apple.product-type.framework"; + }; + 615C831BCE925ED486B225B87E44926D /* KeychainAccess */ = { + isa = PBXNativeTarget; + buildConfigurationList = 99D1947D468DCEAA4431F1F95263DC3A /* Build configuration list for PBXNativeTarget "KeychainAccess" */; + buildPhases = ( + 70969CE00B19E6C2CA2868F9FA0AE35C /* Headers */, + 4A702EEC54A13B2F366712E2E1EAB9DA /* Sources */, + 1EAA3BD0F5BEEE46CCBAA84201853CB8 /* Frameworks */, + 51833BAA88321210CC48C9DF8B11D18B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = KeychainAccess; + productName = KeychainAccess; + productReference = E8EE7F078656FABB8F6821D10FF994BB /* KeychainAccess.framework */; + productType = "com.apple.product-type.framework"; + }; + 84928EB4A33F10E1AA949FEAF3331CBC /* Pods-Services */ = { + isa = PBXNativeTarget; + buildConfigurationList = F8BFF7D89DB99B737428DD3707FD5D7B /* Build configuration list for PBXNativeTarget "Pods-Services" */; + buildPhases = ( + 8823DEEADB239F8D563D480A7126611F /* Headers */, + CE1417F12B0D403D920EE8649D6BCE20 /* Sources */, + 0D430FA595C12BF6C51B1E5D7DA62489 /* Frameworks */, + C11E7BDF2E6C313A4F60A08E15DCEFF2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F9BEA3D05D836C128E1EDBBAFDABF6FA /* PBXTargetDependency */, + A728DED6CCF880273ABA7EFE670E66E8 /* PBXTargetDependency */, + 422FB7CBA9A5E66716BF7D32B20BC3CC /* PBXTargetDependency */, + B064B397B1B19FCEC53DE596BB5C0833 /* PBXTargetDependency */, + C5EC860D7657808CD293D2BD71951F4E /* PBXTargetDependency */, + B2BA21FF54B70130E1D8C04B705D1870 /* PBXTargetDependency */, + 4A2CD178186F35B9D483E5C5673CC3C8 /* PBXTargetDependency */, + ECCC460C69DA33393BD4B7A85952E4A2 /* PBXTargetDependency */, + ); + name = "Pods-Services"; + productName = "Pods-Services"; + productReference = 029DC932573FD3CFF2AB08725C770343 /* Pods_Services.framework */; + productType = "com.apple.product-type.framework"; + }; + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = C16269269CE2C3CF48FAFB11DDCA540B /* Build configuration list for PBXNativeTarget "GoogleUtilities" */; + buildPhases = ( + 1E515CC83C1A6C69B90E75E32C99344A /* Headers */, + FDE508ACFBAA15FFA7AE92A887609FC4 /* Sources */, + AAEE8989AA8CAA1C579BE02343C9D362 /* Frameworks */, + 9B0D5429D800A5F0CBBC8F98BD8769DB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GoogleUtilities; + productName = GoogleUtilities; + productReference = B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */; + productType = "com.apple.product-type.framework"; + }; + 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */ = { + isa = PBXNativeTarget; + buildConfigurationList = E242987B250CB1C0EA9B99A80377B33E /* Build configuration list for PBXNativeTarget "SimulatorStatusMagic" */; + buildPhases = ( + BC611EA94FEA3BF8D61D449B9247327D /* Headers */, + 5246328C1BA4A682124E2CDBB1DEE64E /* Sources */, + 4071E424BB335DEAE15B6918D860D684 /* Frameworks */, + FA92C849D249650342DC1C9D39CB9943 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SimulatorStatusMagic; + productName = SimulatorStatusMagic; + productReference = A787CDE742CEB6FDF5F73F556D790691 /* SimulatorStatusMagic.framework */; + productType = "com.apple.product-type.framework"; + }; + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */ = { + isa = PBXNativeTarget; + buildConfigurationList = F7527E454CF938C5B4E80CDBBF13A340 /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */; + buildPhases = ( + B8851F99376F0F8A8D9CEE158F4A4DF5 /* Headers */, + DA2F1326EFD7678C7B840359CE5AD4BD /* Sources */, + 28D36CD0B6FFBB03EEF67B156AEE1B4C /* Frameworks */, + 14D113BA84B4EB0790747FAAEF8F70E7 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3131B40EE1FD5708C374043FCDEB6F34 /* PBXTargetDependency */, + BC7EE9A83BC83C8B1EA0B865DB3E3542 /* PBXTargetDependency */, + ); + name = FirebaseInstanceID; + productName = FirebaseInstanceID; + productReference = 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */; + productType = "com.apple.product-type.framework"; + }; + A983A2D06C5B6AA3D6ABA5CCC0A16725 /* OHHTTPStubs */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1B3AA62DD852E489C6FA81F9BAE7F98C /* Build configuration list for PBXNativeTarget "OHHTTPStubs" */; + buildPhases = ( + CD7D21AA0812F3958596A40163651653 /* Headers */, + 14DB4251EE88C3CF6615D70066A2E008 /* Sources */, + F833EC5D09A5161EE957E89F80A80BC7 /* Frameworks */, + F8510BB76B60A76AC6782DABF03116F8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OHHTTPStubs; + productName = OHHTTPStubs; + productReference = 17E33041B314FA837A3CAEB9DF3CDE9F /* OHHTTPStubs.framework */; + productType = "com.apple.product-type.framework"; + }; + BB3523197B248933C6F141B6DC5FCD45 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 860FD77954D8865C1B7965B630EFD07E /* Build configuration list for PBXNativeTarget "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests" */; + buildPhases = ( + 03049833CA31385BB30D4A6974B16E79 /* Headers */, + 7EC84A62F5C6445BBB588B1029A01E3F /* Sources */, + A2696FAB0EC2BE55C4464984FF5957B7 /* Frameworks */, + DCBD146301C92925067AC001E3CAB843 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C6ADDAC46BAE790B5E2894C3F6260371 /* PBXTargetDependency */, + 4137DDB2C909FCCC6EE183822D284889 /* PBXTargetDependency */, + 098C54DAA4FCC297C2C34CF4A339E9BB /* PBXTargetDependency */, + CD3657C180695BFBCC9BB851EF1F5E46 /* PBXTargetDependency */, + 4EC338261083E73909D5E7761E10663A /* PBXTargetDependency */, + 9C0856EC0531FA945CB0621FE3B0AAFB /* PBXTargetDependency */, + 75E9BF21F22F51AE7813D23E3EFC0E63 /* PBXTargetDependency */, + DF830C96531680BABA48C2DEBA893DA2 /* PBXTargetDependency */, + 862FD4C3E56F3C7137D8850907F3977C /* PBXTargetDependency */, + D6CCD2C4CEAD112F1B79C0511A89B945 /* PBXTargetDependency */, + 05F2B7C2AC224938D72C5368FF54B6D6 /* PBXTargetDependency */, + 691941D976E70777EFB79ACA1FAEA580 /* PBXTargetDependency */, + 4211219AAF1105EA85D339F96FAC97C7 /* PBXTargetDependency */, + 454908D79BFF91B366565764B2AA14FB /* PBXTargetDependency */, + B705B74B1463E42DE7E58C97AEF2C0A4 /* PBXTargetDependency */, + 5B23281F47748FD6F812B36B1E0FADA1 /* PBXTargetDependency */, + 1C4DCFA1BE3C33FFE254E4C6ABD23A54 /* PBXTargetDependency */, + D6B9451245EC7F755751840A10706B3B /* PBXTargetDependency */, + 3A831672CE66EA90565FF7F71B378748 /* PBXTargetDependency */, + 0ED8426B13D5F2589FD2F141922C3931 /* PBXTargetDependency */, + 4646A36224F955E4FEE7281D538C5357 /* PBXTargetDependency */, + 6B9755FCC79EF45B735CB71F97B8B2E4 /* PBXTargetDependency */, + A55A50E0AF2679328836112D31C109E0 /* PBXTargetDependency */, + C3CBD8D2CA61651CE4EA1EDFF8CCD19F /* PBXTargetDependency */, + ); + name = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests"; + productName = "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests"; + productReference = 8B0B7D7F03E7C5408A9FEDE21398424D /* Pods_{{ cookiecutter.project_name | replace(' ', '') }}_{{ cookiecutter.project_name | replace(' ', '') }}Tests.framework */; + productType = "com.apple.product-type.framework"; + }; + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */ = { + isa = PBXNativeTarget; + buildConfigurationList = E481993470B5B9DFECE3140821C2904E /* Build configuration list for PBXNativeTarget "nanopb" */; + buildPhases = ( + 31917A544DEDF75840A86242DA086C54 /* Headers */, + 51D152A4042A7782D0F5D353F38B0335 /* Sources */, + B18D41FB07D1B0D40F34100516637DCE /* Frameworks */, + A3A4F80C8BD691D6FE533EA760B8E453 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = nanopb; + productName = nanopb; + productReference = 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */; + productType = "com.apple.product-type.framework"; + }; + E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = A304035945DB998EEDDC0634D2BF9F26 /* Build configuration list for PBXNativeTarget "Swiftilities" */; + buildPhases = ( + 5ACB9E7F9554486F77804743DD21C9FF /* Headers */, + 1DFF0C3ABC9844B34CAB74D19D7E3047 /* Sources */, + A9CBED312356F3CEFCFBBCD19C51292D /* Frameworks */, + AA45778E54DD71EF3D1CCCCE2892D362 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Swiftilities; + productName = Swiftilities; + productReference = F7696B90A3B3D1C34C7E852254DD74F1 /* Swiftilities.framework */; + productType = "com.apple.product-type.framework"; + }; + EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */ = { + isa = PBXNativeTarget; + buildConfigurationList = 47242F938FAF8F33076BEC83B73F1607 /* Build configuration list for PBXNativeTarget "Alamofire" */; + buildPhases = ( + E1271C58F3B4DED1AC9FAFC325A29CAF /* Headers */, + 03A33151D245B121EBACF7A802F3D6F3 /* Sources */, + 3ABCC0FD127A6AC59FE23898248C80CF /* Frameworks */, + 82C776FC8950365EBBC6FD941521EF6C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Alamofire; + productName = Alamofire; + productReference = 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */; + productType = "com.apple.product-type.framework"; + }; + FCD9915FE83842AE0201096155515772 /* AppCenter-AppCenterDistributeResources */ = { + isa = PBXNativeTarget; + buildConfigurationList = DF9887486229B1728B84F6155310DF6E /* Build configuration list for PBXNativeTarget "AppCenter-AppCenterDistributeResources" */; + buildPhases = ( + FDC0763AA66CE4E9E3DFE8FAB15F9CB4 /* Sources */, + C5AF32A927179B590C49D6A14BF9158E /* Frameworks */, + DAFA3C5C2162D3C04C2CE530638C4F85 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "AppCenter-AppCenterDistributeResources"; + productName = "AppCenter-AppCenterDistributeResources"; + productReference = 11AF731E4071DCD5E34B4CA294302B92 /* AppCenterDistributeResources.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = C437B8DB3B41FE0E5ACEAF497FD4A0AF /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */, + 4607A9D579EE69C57F52971930107170 /* Anchorage */, + A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */, + FCD9915FE83842AE0201096155515772 /* AppCenter-AppCenterDistributeResources */, + 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */, + C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */, + ABB048B191245233986A7CD75FE412A5 /* Fabric */, + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */, + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */, + D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */, + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */, + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */, + 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */, + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */, + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */, + B593490A33943610DC035C394E10D07A /* Instabug */, + 615C831BCE925ED486B225B87E44926D /* KeychainAccess */, + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */, + A983A2D06C5B6AA3D6ABA5CCC0A16725 /* OHHTTPStubs */, + 44E83D2F8D3A4919879F6D9FA69CBC61 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }} */, + BB3523197B248933C6F141B6DC5FCD45 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests */, + 84928EB4A33F10E1AA949FEAF3331CBC /* Pods-Services */, + 470FE31978DC918618A329D8B55C85FF /* Protobuf */, + 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */, + 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */, + 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */, + E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */, + 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 14D113BA84B4EB0790747FAAEF8F70E7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1963B15BA5DDF39E925E404B1B5C69D8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D6135916B343D7E548A3F64DBFE6EF8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51833BAA88321210CC48C9DF8B11D18B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64B88C84E52D7233869509EAEC6387F2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 82C776FC8950365EBBC6FD941521EF6C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 88B8A813538905511C304057DC4AC323 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9B0D5429D800A5F0CBBC8F98BD8769DB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A3A4F80C8BD691D6FE533EA760B8E453 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AA45778E54DD71EF3D1CCCCE2892D362 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C11E7BDF2E6C313A4F60A08E15DCEFF2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2335386EAEE724F85DA53C2B57D58AC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAFA3C5C2162D3C04C2CE530638C4F85 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AED93C5125D8ADFC97325BC4BDEE8F53 /* cs.lproj in Resources */, + C7EC6507F6038550A48154729F095B52 /* de.lproj in Resources */, + A00E351731E9CCAE152C5B88D885F776 /* en.lproj in Resources */, + 8F1FF94F0311B30034EF2698971AD690 /* es.lproj in Resources */, + 10239177A8AE0CD597F3FDCCDAC21FFE /* fr.lproj in Resources */, + 44B74653D503CB502B265C0366ABF103 /* it.lproj in Resources */, + E2B5FF0AD096653DA71FEF1BBDC6233B /* ja.lproj in Resources */, + 91E15F3267E641CB6282B424CE389263 /* ko.lproj in Resources */, + DBC85A7FC433639F2460B8ACA3A55882 /* pl.lproj in Resources */, + EC29582AC7D6FAE74A58A4795B136544 /* pt.lproj in Resources */, + 6F7BC8C09DBD46C7EAB60340AA5AD1A4 /* ru.lproj in Resources */, + AF9BB102EA05092BA8BAB13BCA806CEB /* tr.lproj in Resources */, + 56284F2A2FBC7E52A29EA14CA7DC047A /* zh-Hans.lproj in Resources */, + 8CCB4DFC6700B70BDB65D48791A47479 /* zh-Hant.lproj in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCBD146301C92925067AC001E3CAB843 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1E3FEBB4ED67C9E1AF276D80B54F7BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8510BB76B60A76AC6782DABF03116F8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA92C849D249650342DC1C9D39CB9943 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 03A33151D245B121EBACF7A802F3D6F3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7898A06A3FFC4228F5FC1CD65A7B8F94 /* AFError.swift in Sources */, + 625AC25C0B02E9914E2F7B57ECEDB850 /* Alamofire-dummy.m in Sources */, + 7D4B4A11129ABEBE81CF0A75213D2927 /* Alamofire.swift in Sources */, + 7A746727440E0883EC1F855F0CBA10DC /* DispatchQueue+Alamofire.swift in Sources */, + 7B9E46226BDFABC5A56EACCCAB550F13 /* MultipartFormData.swift in Sources */, + 61C1F86EDCE280896041FC1FC3DD8187 /* NetworkReachabilityManager.swift in Sources */, + 59DB4ECFCA9DC741DFF14E4456709E22 /* Notifications.swift in Sources */, + ACF4FD5B728533D8559BB12F6428EC2E /* ParameterEncoding.swift in Sources */, + AC38CF40E73B97EFAB79BBE6B56C8731 /* Request.swift in Sources */, + 3D65EF2ED72527D8BD4359402DC8DE54 /* Response.swift in Sources */, + C1676FB1FF537AED93DB44C1582AC152 /* ResponseSerialization.swift in Sources */, + 2D409981B90BFACE059F7069003F5372 /* Result.swift in Sources */, + 49346BA8A9F65D4EB67A452D73543353 /* ServerTrustPolicy.swift in Sources */, + 2FE5FAA4B2358E5E17D36BDB048F9160 /* SessionDelegate.swift in Sources */, + 4DE36299CE267FCDD391EABEA81FFD85 /* SessionManager.swift in Sources */, + 3684FB4C4B318425C246914FE763A0CC /* TaskDelegate.swift in Sources */, + 2BF26FA6F5CA189C337AD83F534BC3D7 /* Timeline.swift in Sources */, + 5A08019AA5486E6DCA36E4EBD3C52A1F /* Validation.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 14DB4251EE88C3CF6615D70066A2E008 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F08BA4C77195B13666BF9D048734345 /* NSURLRequest+HTTPBodyTesting.m in Sources */, + 50B4399E699415F041C1E8E4DB7A1D07 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */, + 7BDE5F52B1111A7404B4B32EF8C5857E /* OHHTTPStubs-dummy.m in Sources */, + DCED874D6F57DD0E744C345B53E96C3B /* OHHTTPStubs.m in Sources */, + EC85906F2F06B19325232E7A96846CD3 /* OHHTTPStubsMethodSwizzling.m in Sources */, + 4996917AB6F783603F868111BEA8E18B /* OHHTTPStubsResponse+JSON.m in Sources */, + 6C47FCB1BC1088F8D9ECA92E2D2C0EE1 /* OHHTTPStubsResponse.m in Sources */, + D3B02CDBEEA6CB4AFA124B0D8FA73C06 /* OHHTTPStubsSwift.swift in Sources */, + 786F3F286C9376BDF33F3008E351E6F5 /* OHPathHelpers.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1DFF0C3ABC9844B34CAB74D19D7E3047 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6E8015F43C774A2A6B848A4850A5A01B /* AboutView.swift in Sources */, + 515B9D3F0278919FFC0BA69A4A50BF3E /* AccessibilityHelpers.swift in Sources */, + 00B3DFC8711DBA5BEFD89F179EFD44C1 /* AcknowledgementsListViewController.swift in Sources */, + 3B8C1EA2A930ED9F1F28457FF7860F06 /* AcknowledgementsListViewModel.swift in Sources */, + B21176F4F4CEC62BCAFC4FEB1712C2B6 /* AcknowledgementViewController.swift in Sources */, + D33AB83EB8EE0B969A5F68BAF790EC60 /* AppInfo.swift in Sources */, + A263672C857DB63F9F371F1E52FDE51A /* BetterButton.swift in Sources */, + F9956CE423EE435E6B36C133CDD5D27B /* CGFloat+DeviceSize.swift in Sources */, + 84F2EA2BB1C1901EA0A3A1F71919F915 /* CGSize+DeviceSize.swift in Sources */, + 8FD25BB2E0968A8C1C27B4383552FB40 /* Clamping.swift in Sources */, + 9D37E82FFBA10D1CAC0BE6FA8C3B17E2 /* Compatibility.swift in Sources */, + 0B9AC443AC8498AB675F72F8A84D961D /* CoreDataStack.swift in Sources */, + 64608DAE6E2BA2943D7382FC8434201E /* CubicBezier.swift in Sources */, + C2DFB45D6494E63C9993006A15DE55B8 /* CurveProvider.swift in Sources */, + 8D1F1562F8784E50D8E14D44A8B915ED /* DefaultBehaviors.swift in Sources */, + 98F45B8FD93C9BF709915C0ACC7D316D /* DeviceSize.swift in Sources */, + B60414F93325024469AAB0F4B1D4141E /* FeedbackPresenter.swift in Sources */, + C92E53E0F9CE7D32CAEE125353487361 /* FieldValidator.swift in Sources */, + 73C84761F0777ED77BDA9657F0D88C33 /* FloatingPoint+Scale.swift in Sources */, + 133BA9EE26B755C23B694417B33A6936 /* FormattedTextField.swift in Sources */, + CD780A5F99BC76FD2C51EEF2E495CACA /* GradientView.swift in Sources */, + FCEF602D4650E2F192CE13FE12DE83CE /* HairlineView.swift in Sources */, + 8E1D665623C95E8500B9B69BFE963089 /* IndexPath+Extensions.swift in Sources */, + 31F595EB1AE5D570993770123D9A2A5B /* Keyboard.swift in Sources */, + 7D8BB2A430E5C20AF8657A11C9F48016 /* LicenseFormatter.swift in Sources */, + 41D8B6DE590FB9C57F9878F4A384C223 /* LifecycleBehaviorViewController.swift in Sources */, + BAA7A298BF2D071AE6077551CABDA17A /* Log.swift in Sources */, + B1AB9C0D1668DA7D1FB8B05625FE15BB /* NavBarHairlineFadeBehavior.swift in Sources */, + 028B2CECCB9AEA8424D7C00138A38431 /* NavTitleTransitionBehavior.swift in Sources */, + 58052E699714C0A50B87E6259F53F415 /* PlaceholderTextView.swift in Sources */, + 4137F7B8D747E67F776B744E4FF5A116 /* Protocols.swift in Sources */, + 790C5DA2D20D2290D35CD413F051C02D /* Shapes.swift in Sources */, + FBA2DE155485C184B1D2D04B60B5F4F0 /* Swiftilities-dummy.m in Sources */, + D560EF907E1B219904938C32DCA07877 /* TableSection.swift in Sources */, + 02FBDFBD52654C16E8616F45114FAA14 /* TailoredSwiftTextView.swift in Sources */, + D47C36356662BB1CCEC086A9339876E0 /* TintedButton.swift in Sources */, + 9AEA26145F40861CBB60CF404C36C469 /* UIColor+Helpers.swift in Sources */, + 48DD3117F88694C0FD530B7D951E585F /* UIImage+Tinting.swift in Sources */, + 337AF23300B055F9D0AF0BB5AC2F55E9 /* UIStackView+Helpers.swift in Sources */, + 3EA25AB8FC4048123BF2D50D8AEBEFA7 /* UITableView+Extensions.swift in Sources */, + D08829137C1C28D74067CE0D2C9EEF00 /* UITextView+Extensions.swift in Sources */, + 95C6E0D347DA6F768468BF0929F8A84C /* UIView+KeyboardLayoutGuide.swift in Sources */, + 0100B51AAD85D2A5B7C3725618933398 /* UIView+Lookup.swift in Sources */, + 6C12C62F4EB60D4AD5F161942A4D7A1F /* UIViewController+Deselection.swift in Sources */, + A0A162DA5D4BB9A0DAFA3B60DE55130B /* UIViewController+Lifecycle.swift in Sources */, + E93C17002FD7C60CDD5B227371E6AE34 /* UIWindow+RootViewController.swift in Sources */, + 28292C6F27C2567FFD9A0C3130CFC626 /* ViewControllerLifecycleBehavior.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 29333CABA17205542DF156993C524977 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD0155BAAB0AF2CAB66FF0A801DD974 /* AccessibilityHeadingLevel.swift in Sources */, + 1E460A03738161788BA4D0258D3C2657 /* AdaptableTextContainer.swift in Sources */, + E5C352E6C1B3288A651344F557E2A10B /* AdaptiveStyle.swift in Sources */, + 3957709DBEF6C37401EF8F32B962985D /* AdaptiveStyleTransformation.swift in Sources */, + F56B615204B36C3D1287663301D9ED63 /* AttributedStringTransformation.swift in Sources */, + E1C7D68DBCE3516AFDBB93D344E4710D /* BonMot-dummy.m in Sources */, + 06B290D6C5B112EC54DE4AAF0921A969 /* Compatibility.swift in Sources */, + E79E53BD4BED86182EE57B0E7D1FB563 /* Composable.swift in Sources */, + CDA29493785FE82167BBBD3348DFB2D5 /* ContextualAlternates.swift in Sources */, + DC7608F13970D10F8031C34305B4E2FB /* EmbeddedTransformation.swift in Sources */, + 49B7354094136C862C02D3564F82F95C /* Emphasis.swift in Sources */, + F628B678C1D14102D5A6B8E8A369F7FD /* FontFeatures.swift in Sources */, + AFA19EAA3DF13F4E416F836CDE2C1251 /* FontInspector.swift in Sources */, + 672DC3874BA0AB02B90F8C35DE880034 /* Image+Tinting.swift in Sources */, + 5B7FBA1711906689F88D73F89241C604 /* Ligatures.swift in Sources */, + 27168CA32C4871EEE4C1CE2D5909485F /* MutableCopying.swift in Sources */, + D05BF98677EB4739C37C9533E8D877A0 /* NamedStyles.swift in Sources */, + DC6F351B5AAB3C9A2D73772E8BD102B6 /* NSAttributedString+Adaptive.swift in Sources */, + 2EF7C4DD8AE3B593B8DF4E2935543F45 /* NSAttributedString+BonMot.swift in Sources */, + 3AE9A26503715569C678C2C331591663 /* Platform.swift in Sources */, + 002B61DB441C6864402B2620001F2D24 /* Special.swift in Sources */, + 4C1E5B258AF3CD751A7D6DC2F9EFDB64 /* StringStyle+Part.swift in Sources */, + 1FA20690DF9A5043204742E88A203343 /* StringStyle.swift in Sources */, + 67DE466AD41481FEF9115827C53B66FC /* StyleableUIElement.swift in Sources */, + DA1DCD65BFC20A27214C1138C1B92D7F /* StylisticAlternates.swift in Sources */, + 42BC5786C34E1EB3171356AF8E67E607 /* Tab+Adaptive.swift in Sources */, + F8E578B6F9EE4FDDEDF54894A8FCD15C /* Tab.swift in Sources */, + E3A6BE04CAE18910FF90BC707A1B586E /* TextAlignmentConstraint.swift in Sources */, + 42D8642270868B9E53CD23BE32323A0C /* Tracking+Adaptive.swift in Sources */, + E78643D19759C84B84FA5C437DD5C285 /* Tracking.swift in Sources */, + D8C1006C39A3ED7B8F0EBF65D2E66303 /* Transform.swift in Sources */, + 2BD4A62FFC2595A77CF36ECD209FAC2C /* UIKit+AdaptableTextContainerSupport.swift in Sources */, + 8D67D48F9FE60EA4ECB227C7E5E988BA /* UIKit+Helpers.swift in Sources */, + D8342F77FCB434AAD8975E0386F61252 /* XMLBuilder.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A702EEC54A13B2F366712E2E1EAB9DA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C1EB978E9BF15E1F44EA79EAB899E3 /* Keychain.swift in Sources */, + FD8EAE65C4C2FC32FE51494D63D4D180 /* KeychainAccess-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51D152A4042A7782D0F5D353F38B0335 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A9842F18B9A92D8C8A029ED721E22B3 /* nanopb-dummy.m in Sources */, + 588888EDDEAB87B7AE65F4417BB0895E /* pb_common.c in Sources */, + 82FEC2B074B1B137D892D51E72F583D5 /* pb_decode.c in Sources */, + 8CDCC6382693D52163B893E94EDE484A /* pb_encode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5246328C1BA4A682124E2CDBB1DEE64E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA8774937F99D03BE90B136C8A6A3C55 /* SDStatusBarManager.m in Sources */, + 8B512506674B51BA6D35237363F2B370 /* SDStatusBarOverriderPost10_0.m in Sources */, + AA174969F3D235A0D986C40FA01F8696 /* SDStatusBarOverriderPost10_3.m in Sources */, + 322D81E9DF88D46A7F0B60EF4B7CB1CA /* SDStatusBarOverriderPost11_0.m in Sources */, + 8E1278F983579FE2CCEED68C625ABFF6 /* SDStatusBarOverriderPost12_0.m in Sources */, + 49A539B6B325126F22AC170396E5B6EC /* SDStatusBarOverriderPost8_3.m in Sources */, + 4C650C838B9A46B8869FAC4ED9167B3B /* SDStatusBarOverriderPost9_0.m in Sources */, + E052E19761060467DB062D60D88F5536 /* SDStatusBarOverriderPost9_3.m in Sources */, + B1169761CF66CB7C48BFF5F13A2A89A6 /* SDStatusBarOverriderPre8_3.m in Sources */, + 629542A04865B500B62B43F92C8865D1 /* SimulatorStatusMagic-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 72B8E25E992B707A92C7C56A5B4D1DD0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BD9628048902C3E6580C8916350A4EE7 /* Any.pbobjc.m in Sources */, + F6FF11572A5F8C02E4BA95CD335737E6 /* Api.pbobjc.m in Sources */, + 29F77423AD4D91EA6AA353C23B5C80FA /* Duration.pbobjc.m in Sources */, + 722C5094761B72D30EB0CCB1CBD1BB5A /* Empty.pbobjc.m in Sources */, + 88E84F132638AF1A4D47AC5A0641131F /* FieldMask.pbobjc.m in Sources */, + 3200DB013281B43E28A5C67E98EDCF1B /* GPBArray.m in Sources */, + 9A7E0722E552D06D26AF4A48C0FC02C7 /* GPBCodedInputStream.m in Sources */, + E914909867188AF11D12A4292BBC9729 /* GPBCodedOutputStream.m in Sources */, + 6F7B7BD79C3CFF57A0AA78D63E5E3875 /* GPBDescriptor.m in Sources */, + 8EFC6634D956643DB4EB307460CE67D0 /* GPBDictionary.m in Sources */, + C264488148DA19FD69AD0378C76E7DB9 /* GPBExtensionInternals.m in Sources */, + A0F9B76BF94A692BF96E87085472F70D /* GPBExtensionRegistry.m in Sources */, + 53DC83DDE0F07B1E642EDD0A2FDFCC1B /* GPBMessage.m in Sources */, + DD1C25E78F7402AFE7D53F6CB0EC6459 /* GPBRootObject.m in Sources */, + 969588515E0889063CB93DA45160D18A /* GPBUnknownField.m in Sources */, + D3044F1325FD2E1F21B84CB5E9F5CD86 /* GPBUnknownFieldSet.m in Sources */, + AE2FB5B79FD2943549EF53126CD94862 /* GPBUtilities.m in Sources */, + 12C27A0E31DE9B1B0B5E54C2C429BD54 /* GPBWellKnownTypes.m in Sources */, + D2801FDD33B72D4C72A170C413AA7D71 /* GPBWireFormat.m in Sources */, + 3864DBFDFD3CA45C50C5E35FED55D1C6 /* Protobuf-dummy.m in Sources */, + 817FFB25CEB300C681DBD8283FF19BA1 /* SourceContext.pbobjc.m in Sources */, + 513E4B1817532226E5F18D5BC9616970 /* Struct.pbobjc.m in Sources */, + B2C05E981C8FAAEA0F53F712918CBEBF /* Timestamp.pbobjc.m in Sources */, + 884A014FF635DEF5D4FBF2CED48D3610 /* Type.pbobjc.m in Sources */, + FF7B4E979DC08115710FD5CF868DFABF /* Wrappers.pbobjc.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7EC84A62F5C6445BBB588B1029A01E3F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8E307CE212F087956B2835C792FFC79C /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8AD0FEC519E2F25A92EFA4A40E97C225 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 49831F5B3224292A50B5E474627F4066 /* FIRAnalyticsConfiguration.m in Sources */, + 51E49408AF7F12CE0559236B11C26465 /* FIRApp.m in Sources */, + E20902716A8AA163A00FC6FE3817D4C1 /* FIRAppAssociationRegistration.m in Sources */, + 111E7E93B775DC49472ABF1CDC8BD6C7 /* FIRBundleUtil.m in Sources */, + 3322584F7CF6DD027B79F6BCA4651CA1 /* FIRComponent.m in Sources */, + 2612E406DE2FDD81958D99713579DFE4 /* FIRComponentContainer.m in Sources */, + A6DB0753F4D2BE9056C288F6376CD092 /* FIRComponentType.m in Sources */, + D6F46C2555BF94DD17EB5C5137297B7A /* FIRConfiguration.m in Sources */, + 8A3030124B1B48425552E80DADE1FA88 /* FIRDependency.m in Sources */, + 8D56B87617552C4649123F283D3F4383 /* FirebaseCore-dummy.m in Sources */, + 1B5BAD2AE0BDB78D1797A3F079F2DB27 /* FIRErrors.m in Sources */, + F53A883BACBEF618EB01165812EB60A8 /* FIRLogger.m in Sources */, + 3A68C5510ECCCB664B640F57F86435D9 /* FIROptions.m in Sources */, + 69AB47B1E87B21D5AB731A8B4F8A5C6E /* FIRVersion.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B171C95BD079223B02E20B54DAC07B3F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 040519868B2FE15E71CE862276B5FB0D /* Anchorage-dummy.m in Sources */, + 34F9A43BEE167441599A1035E0C14F96 /* Anchorage.swift in Sources */, + A7140404957904FEA7F3949F01B858C0 /* AnchorGroupProvider.swift in Sources */, + B563C657D3678F851A0F8881DC90DB25 /* Compatability.swift in Sources */, + C8BF91ECAD3BF591B752B6C3BCB6761D /* Internal.swift in Sources */, + 13818F8210CF5628758D110549396C75 /* NSLayoutAnchor+MultiplierConstraints.swift in Sources */, + 9307183A631102399452F35E8630D4C1 /* Priority.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C5EDC2EFB9F2A36C846524DD554C6A16 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33C1DC1D1DBDCCD13C278B789AC82B0F /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CE1417F12B0D403D920EE8649D6BCE20 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 623966AD950C81665095F64F9D4201CB /* Pods-Services-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA2F1326EFD7678C7B840359CE5AD4BD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D01F5103E9821505EF578009E14403E /* FirebaseInstanceID-dummy.m in Sources */, + 660EE0BDDC1B6E8665904E38D90D31C6 /* FIRInstanceID+Private.m in Sources */, + 203BE416FA99DFA5A8A48CBFD3D12D1D /* FIRInstanceID.m in Sources */, + 44FB46D5982B3E156F7AA4BEE081B463 /* FIRInstanceIDAPNSInfo.m in Sources */, + 68F48879AF4FFB5542723DDF132E7BBF /* FIRInstanceIDAuthKeyChain.m in Sources */, + 5709B0AB8B9B6E3FD552E4D0E72A40E5 /* FIRInstanceIDAuthService.m in Sources */, + 730B332BFCCE80D74F954AB5D5018B07 /* FIRInstanceIDBackupExcludedPlist.m in Sources */, + 75B139101E0BFF3585B49F931BE977F2 /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */, + D7B354F43D71BF171E85F1A3D460C027 /* FIRInstanceIDCheckinPreferences.m in Sources */, + 75123AA17FF6CF721675F5EFB25EC559 /* FIRInstanceIDCheckinService.m in Sources */, + E88F998AF2E3FABE07308B1454182029 /* FIRInstanceIDCheckinStore.m in Sources */, + 39074F282BFA3893780C3F2330271BFA /* FIRInstanceIDCombinedHandler.m in Sources */, + 7AB1BE129580DE43994C27204D3D9F97 /* FIRInstanceIDConstants.m in Sources */, + 3DA83DFE11641ABBF54EED0F6D91658C /* FIRInstanceIDKeychain.m in Sources */, + A605E2BA73843B1BF04318D1F249E7D8 /* FIRInstanceIDKeyPair.m in Sources */, + D0015B5606D3E07958B6F40D8625B8F0 /* FIRInstanceIDKeyPairStore.m in Sources */, + AB7B824DA74A18F8F235023186B0CB99 /* FIRInstanceIDKeyPairUtilities.m in Sources */, + E27438C8E65CF4DAC905C6026EBACC35 /* FIRInstanceIDLogger.m in Sources */, + 90CDCAD92FF576BA1E27CAC55DF10C91 /* FIRInstanceIDStore.m in Sources */, + 5762BA089A3300D0CC1348BB1C6BF5D0 /* FIRInstanceIDStringEncoding.m in Sources */, + 0E47DE1D5D4C7AA8034D1B7F63774BF0 /* FIRInstanceIDTokenDeleteOperation.m in Sources */, + A4D4A302AEEB0666AEB08B226637D78E /* FIRInstanceIDTokenFetchOperation.m in Sources */, + 79D254191EAC73996F5BD06EFFA4E649 /* FIRInstanceIDTokenInfo.m in Sources */, + EB3DC0691CBB0AF117F1D9D442FA67AA /* FIRInstanceIDTokenManager.m in Sources */, + 40CAB5AAB5CF579001117DA2892ABA3B /* FIRInstanceIDTokenOperation.m in Sources */, + FC9D03E94B1D4725AAA52ED0AFD5463F /* FIRInstanceIDTokenStore.m in Sources */, + 66E368242E78C0FD771A32B6FE1931A8 /* FIRInstanceIDURLQueryItem.m in Sources */, + B5E3F3D139F7AC7686281E983CAEC0B9 /* FIRInstanceIDUtilities.m in Sources */, + DA40FB231BD634D57A958BF90B7D27B0 /* FIRInstanceIDVersionUtilities.m in Sources */, + 1F680A61812FACE2D5115195328CA3DF /* NSError+FIRInstanceID.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ECAA69750FA4F99D92214CCBCCDAF45E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2646BB4FDA2D1690D9DA61405740F25C /* FirebaseMessaging-dummy.m in Sources */, + 63EACF4772E7F89957A22DD4E216C3F6 /* FIRMessaging.m in Sources */, + A6413A77105FCE014808660C4A174018 /* FIRMessagingAnalytics.m in Sources */, + 8625F2607D15296CF239BC97F7BB3EE6 /* FIRMessagingCheckinService.m in Sources */, + 776CAB01CC996B0FBA52C7C6872F0814 /* FIRMessagingClient.m in Sources */, + E851CD56878C963DD7E0CD660FBE4D22 /* FIRMessagingCodedInputStream.m in Sources */, + D7F5B4B7FF371A59B9F5625EC8ECAA7E /* FIRMessagingConnection.m in Sources */, + 6B9902DEB83C255B7F7BE5B97D95CB8C /* FIRMessagingConstants.m in Sources */, + 1B8BC5D48142213B30D7DB0D0B067738 /* FIRMessagingContextManagerService.m in Sources */, + AE1DA43BC4C87D79899149013C1DAD98 /* FIRMessagingDataMessageManager.m in Sources */, + C8AC529DAADB07541D2D33E392CDF169 /* FIRMessagingDelayedMessageQueue.m in Sources */, + 8E06E338A8F1324484A07E102C6085CB /* FIRMessagingExtensionHelper.m in Sources */, + F7CA527CFEF6E3DE6466C6D66D138346 /* FIRMessagingLogger.m in Sources */, + 46132B8EB028FC0BD59C6B8293151984 /* FIRMessagingPacketQueue.m in Sources */, + 6A54BA358BA6EA4B21A472B16B0F2136 /* FIRMessagingPendingTopicsList.m in Sources */, + DD34CF52B04302F2F486A626A57EBE9B /* FIRMessagingPersistentSyncMessage.m in Sources */, + EB9352F06FF1E5906D9D91135967ABB8 /* FIRMessagingPubSub.m in Sources */, + ADEAD2F9475DADEA607C02D303956EBC /* FIRMessagingPubSubRegistrar.m in Sources */, + 70A61B041ADCE42401597F1F1E36A137 /* FIRMessagingReceiver.m in Sources */, + 1735E3217A03B5B4EEFF084033ABE1DD /* FIRMessagingRegistrar.m in Sources */, + 922299C14975D3257CEA7CD05B8230AA /* FIRMessagingRemoteNotificationsProxy.m in Sources */, + 3A1C7551BF0986016F6C2537B5E2733F /* FIRMessagingRmq2PersistentStore.m in Sources */, + F4D84858653EFDD2A8738A28176A44E4 /* FIRMessagingRmqManager.m in Sources */, + E1355ABFA24FFFE7788FFC23A0E5543D /* FIRMessagingSecureSocket.m in Sources */, + CA9D644E80935F7226B7D7105E837792 /* FIRMessagingSyncMessageManager.m in Sources */, + DD904DE0D282B9A9724B76536A085559 /* FIRMessagingTopicOperation.m in Sources */, + E2C7E5A5A237425DA4C72EFF01475076 /* FIRMessagingUtilities.m in Sources */, + 39CE61B6B67AAA879293052A016A9B44 /* FIRMessagingVersionUtilities.m in Sources */, + 857CEBBEB16312172E8DF03B1147377B /* GtalkCore.pbobjc.m in Sources */, + A2C760AD1904241031DE9DDD5DB0E935 /* GtalkExtensions.pbobjc.m in Sources */, + DCE2544D0E3CA203C5FC20C01510DDC3 /* NSDictionary+FIRMessaging.m in Sources */, + 1931E725A11B3C13986AB78A8130111C /* NSError+FIRMessaging.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDC0763AA66CE4E9E3DFE8FAB15F9CB4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDE508ACFBAA15FFA7AE92A887609FC4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 80975D2BEC9BBEB5D026A75D9A42B6B2 /* GoogleUtilities-dummy.m in Sources */, + 748616D83CFB8AD5D5FC47C2EDB8FF36 /* GULAppDelegateSwizzler.m in Sources */, + F36D0E75366326FACC9EB8DE7F4F98F4 /* GULAppEnvironmentUtil.m in Sources */, + 0D9138EF60798B8D013C354FFC3F956C /* GULLogger.m in Sources */, + CB0F1A83E1DFE29F971867BFB285B59D /* GULMutableDictionary.m in Sources */, + 8EC15CDA263AE10AF1D49B82794AFBB4 /* GULNetwork.m in Sources */, + 4D4DD4E2E2F97F489820569260C7BBEF /* GULNetworkConstants.m in Sources */, + 1A57D555A841083C708009478DC31FB5 /* GULNetworkURLSession.m in Sources */, + 1B586862269C42A863000C3B70991A0B /* GULNSData+zlib.m in Sources */, + 3A6073E24514DD7FC8539E5C9BD6FF3F /* GULReachabilityChecker.m in Sources */, + 18104AFA575A3CFB614915516FA8A1EF /* GULSwizzler.m in Sources */, + 59797280DBA2DF4FDD7E2FB08A37D99B /* GULUserDefaults.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 027A71A52AB8D3D436ECDC9CB733277E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AppCenter; + target = A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */; + targetProxy = DF4A594B4218CCA9EF0D5B89B5EFB551 /* PBXContainerItemProxy */; + }; + 05F2B7C2AC224938D72C5368FF54B6D6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = BAE33B3D752C070CD5F2887D4F50B516 /* PBXContainerItemProxy */; + }; + 098C54DAA4FCC297C2C34CF4A339E9BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AppCenter; + target = A3282A5B2437E609EEB85861D7ECE717 /* AppCenter */; + targetProxy = 1F2EFDBE486B46D9BB0ACA670DCE64E5 /* PBXContainerItemProxy */; + }; + 0C26C138EB21155893EB3AAE8342452D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseMessaging; + target = 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */; + targetProxy = E50E5C34A42ACE328C4D101E74D0E458 /* PBXContainerItemProxy */; + }; + 0ED8426B13D5F2589FD2F141922C3931 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sourcery; + target = 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */; + targetProxy = 4C4B6E49A1CB5F547EF7EDA8A2894B2E /* PBXContainerItemProxy */; + }; + 1C4DCFA1BE3C33FFE254E4C6ABD23A54 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = OHHTTPStubs; + target = A983A2D06C5B6AA3D6ABA5CCC0A16725 /* OHHTTPStubs */; + targetProxy = 3103E425B0EDFA9736C768A7D3E015B9 /* PBXContainerItemProxy */; + }; + 21126DE93342F0CFC72E8B0BFF74B7C2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 4809F369638E77D13FBA5FDDC4B279F0 /* PBXContainerItemProxy */; + }; + 3131B40EE1FD5708C374043FCDEB6F34 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 543BCBF2DF409AB1D8FBE0BB138681A9 /* PBXContainerItemProxy */; + }; + 34CC4B4491776D9C45A351FBC15D65D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SimulatorStatusMagic; + target = 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */; + targetProxy = CCD653DB7DAA28F82561ABBA8580BADE /* PBXContainerItemProxy */; + }; + 3792EB87049BCC72EB8B88E35FC33ADB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 66BF61E910A9B80A8316776974C2BB95 /* PBXContainerItemProxy */; + }; + 3A831672CE66EA90565FF7F71B378748 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SimulatorStatusMagic; + target = 95F19093D340358F7EE721EC01F43355 /* SimulatorStatusMagic */; + targetProxy = E9C5672F0CD0FA063A46323C4AC136D2 /* PBXContainerItemProxy */; + }; + 4137DDB2C909FCCC6EE183822D284889 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Anchorage; + target = 4607A9D579EE69C57F52971930107170 /* Anchorage */; + targetProxy = 5B756F4043C0BF271158008CDED79D84 /* PBXContainerItemProxy */; + }; + 4211219AAF1105EA85D339F96FAC97C7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = E327328558089D481E112C8A4A506DE5 /* PBXContainerItemProxy */; + }; + 422FB7CBA9A5E66716BF7D32B20BC3CC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = BonMot; + target = 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */; + targetProxy = 61CD1DC5DB1618415917A6B6B148544A /* PBXContainerItemProxy */; + }; + 454908D79BFF91B366565764B2AA14FB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = A57D1B3D3A7F6453569CBAD3F3B57B2B /* PBXContainerItemProxy */; + }; + 4646A36224F955E4FEE7281D538C5357 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftGen; + target = 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */; + targetProxy = 95B892EE3C9D4BCC89AA02E77558C5CF /* PBXContainerItemProxy */; + }; + 4A2CD178186F35B9D483E5C5673CC3C8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = DF66A2F4782D1A0979660E315CF32196 /* PBXContainerItemProxy */; + }; + 4C5E8A7AE78E64723705A8C4F39294C2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Alamofire; + target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */; + targetProxy = 47C1327AD0E022A8CAD8A8A249109E10 /* PBXContainerItemProxy */; + }; + 4EC338261083E73909D5E7761E10663A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Crashlytics; + target = C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */; + targetProxy = 2E46EEE58DA8EA73341280992D1C5D13 /* PBXContainerItemProxy */; + }; + 509CCF144E767C197328128D373A1367 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalyticsInterop; + target = D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */; + targetProxy = 1FDC68635BD8EB1847D7ABA3BDED5D08 /* PBXContainerItemProxy */; + }; + 517C4D4310C32500D8D3C4AFB217A87A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Protobuf; + target = 470FE31978DC918618A329D8B55C85FF /* Protobuf */; + targetProxy = 148469CADF8690152BAB10A58272A43F /* PBXContainerItemProxy */; + }; + 57A98EA8D303A644FA7B50E4295B8171 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = C6B51788BF5B5F1CA75F34172EAC8C66 /* PBXContainerItemProxy */; + }; + 5B23281F47748FD6F812B36B1E0FADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KeychainAccess; + target = 615C831BCE925ED486B225B87E44926D /* KeychainAccess */; + targetProxy = B269AA35A62F09500537A4BA3BFB44C3 /* PBXContainerItemProxy */; + }; + 5C27114E1234A898AE9167984987A6BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Instabug; + target = B593490A33943610DC035C394E10D07A /* Instabug */; + targetProxy = 5802AA2B78C7A3E6CF58C77D762D71E9 /* PBXContainerItemProxy */; + }; + 5CE6985057CE4B265103CF4F42193E36 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = 02B643491EF1939B6406629306F2675E /* PBXContainerItemProxy */; + }; + 5F429333A5E8F5B0843B8383C878CEDD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = BE218348DB050D18EB6D52F098627920 /* PBXContainerItemProxy */; + }; + 691941D976E70777EFB79ACA1FAEA580 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseMessaging; + target = 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */; + targetProxy = F08459BC4BC97915AAF676A70BA1044E /* PBXContainerItemProxy */; + }; + 6B9755FCC79EF45B735CB71F97B8B2E4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = DCD1C96ECC57BB8FC7BB0C12A709B9F1 /* PBXContainerItemProxy */; + }; + 72C383DDA0C3B15B45C1BBE8168E7C32 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Fabric; + target = ABB048B191245233986A7CD75FE412A5 /* Fabric */; + targetProxy = 3DB056970030F95365323DB7D483F0E4 /* PBXContainerItemProxy */; + }; + 73A206221EDC7792C0724E183F29C491 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 93FC40FACD2A3CAE5B749D36454B21BA /* PBXContainerItemProxy */; + }; + 75E9BF21F22F51AE7813D23E3EFC0E63 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = FCB8621B4850804581799AA75D809CD9 /* PBXContainerItemProxy */; + }; + 76368B6D12BB326EEFA9898C11C103BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = BonMot; + target = 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */; + targetProxy = F83820FC705E1ACB652B680E9ED10441 /* PBXContainerItemProxy */; + }; + 790A3D878446B70A5A20256D674AB5E1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Crashlytics; + target = C0E41540D6862472ED7F2FA11669BE1F /* Crashlytics */; + targetProxy = 5377C294E50C7447C27E7C2D9D0BC8C4 /* PBXContainerItemProxy */; + }; + 80661FD0776FF5CE9CEA1E2D72C1B901 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseMessaging; + target = 5895B432FE4D2F6826C8FF25A09DB6D2 /* FirebaseMessaging */; + targetProxy = 689919C1E5546B4C5075358DC52F3565 /* PBXContainerItemProxy */; + }; + 83F2C143D8BEF77B7C4759F0CAFB4E62 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = 2A7CCB51109B88316A5FC993FB897CEB /* PBXContainerItemProxy */; + }; + 862FD4C3E56F3C7137D8850907F3977C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalyticsInterop; + target = D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */; + targetProxy = F3A392E1ED6D4068A572BD13DC958074 /* PBXContainerItemProxy */; + }; + 912865061B33024F53771995A880334E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Protobuf; + target = 470FE31978DC918618A329D8B55C85FF /* Protobuf */; + targetProxy = 1BF24697EA008F1406020E754EF90367 /* PBXContainerItemProxy */; + }; + 9C0856EC0531FA945CB0621FE3B0AAFB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Fabric; + target = ABB048B191245233986A7CD75FE412A5 /* Fabric */; + targetProxy = 5576D78AFE2208B1EEFB5282D84D1F08 /* PBXContainerItemProxy */; + }; + 9F9E6213111F42F60CF9E3049030C0EC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = F7B77B6FF52752D1C86E594584C3D247 /* PBXContainerItemProxy */; + }; + A3560B04C6C7550C49D3509E4F985634 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = CC51CF93141CEA0C62DE97225C0BC04E /* PBXContainerItemProxy */; + }; + A55A50E0AF2679328836112D31C109E0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Swiftilities; + target = E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */; + targetProxy = 1A12587DD794CA9955F23A75370F8EAD /* PBXContainerItemProxy */; + }; + A728DED6CCF880273ABA7EFE670E66E8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Anchorage; + target = 4607A9D579EE69C57F52971930107170 /* Anchorage */; + targetProxy = C80C2AF874999BC32CD68D52CF8B6442 /* PBXContainerItemProxy */; + }; + A8FE2505F0526DA98700BDEF778002CA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = D9CCC0B18E86FDC85771011139ACDCD4 /* PBXContainerItemProxy */; + }; + B064B397B1B19FCEC53DE596BB5C0833 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KeychainAccess; + target = 615C831BCE925ED486B225B87E44926D /* KeychainAccess */; + targetProxy = DB41FC5EB5ED2499B0E89BB46AA4359B /* PBXContainerItemProxy */; + }; + B246D60A4784E7242E6F9573F6581752 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 75EA1E73941199F90021A0EBD5ED4264 /* PBXContainerItemProxy */; + }; + B2BA21FF54B70130E1D8C04B705D1870 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftGen; + target = 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */; + targetProxy = 08148E3EFA12C37CE29E49C3C7EF9167 /* PBXContainerItemProxy */; + }; + B5290BC5AF5A74B7D2919728FDE4472E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 4C0638D0D195A9000851F687C36E3AF2 /* PBXContainerItemProxy */; + }; + B59975B1711C1B93F51408259602A32F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = DEF897143670388E42D9901AD7FECCDC /* PBXContainerItemProxy */; + }; + B705B74B1463E42DE7E58C97AEF2C0A4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Instabug; + target = B593490A33943610DC035C394E10D07A /* Instabug */; + targetProxy = FE3AF2118BF9BD4601F3A147DBC26D4C /* PBXContainerItemProxy */; + }; + BC7EE9A83BC83C8B1EA0B865DB3E3542 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 6ECBB905773B62DD8276A7843DE12298 /* PBXContainerItemProxy */; + }; + BC9C5B4317B57C84FDC286747A6C68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "AppCenter-AppCenterDistributeResources"; + target = FCD9915FE83842AE0201096155515772 /* AppCenter-AppCenterDistributeResources */; + targetProxy = FC1D9ED47627FC05FEF6B4B3B5CDB53C /* PBXContainerItemProxy */; + }; + C3CBD8D2CA61651CE4EA1EDFF8CCD19F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 73FE5A0BD5D3991167C7C54DD4D446DA /* PBXContainerItemProxy */; + }; + C4D6DC5312308B518D11684361884474 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 7A591D0D32FC2DC7C5953B14551C8425 /* PBXContainerItemProxy */; + }; + C5EC860D7657808CD293D2BD71951F4E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sourcery; + target = 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */; + targetProxy = 33807B5A769F0C36650DF5EE9C76AB54 /* PBXContainerItemProxy */; + }; + C6ADDAC46BAE790B5E2894C3F6260371 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Alamofire; + target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */; + targetProxy = B5EC11065BDE7CEAB67D207F576271FB /* PBXContainerItemProxy */; + }; + C9EE7669C499C214D32673DA70F448B1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Fabric; + target = ABB048B191245233986A7CD75FE412A5 /* Fabric */; + targetProxy = BF2E36C9AB9868362ECE4F7D15CA684C /* PBXContainerItemProxy */; + }; + CCB4B2FB4874EF61E26C0C42BF0A95E6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 689D82AE9C6AAEF561CBC45F0C3F37D8 /* PBXContainerItemProxy */; + }; + CD3657C180695BFBCC9BB851EF1F5E46 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = BonMot; + target = 4C48FB7D363771FBD71AB44C090CB586 /* BonMot */; + targetProxy = 2E884F9A0CD78CCADB89B607F8BDB639 /* PBXContainerItemProxy */; + }; + D0405CD352F9BA331E0835E76731E1D5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftGen; + target = 1E798429DCFA7906F6625CCFC1088744 /* SwiftGen */; + targetProxy = BBA3C65F4427758819F8FE0EB02A684A /* PBXContainerItemProxy */; + }; + D26A457C36225DE41C7BB4FD7A7FF254 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = FBBD79508378F74FDD48FDE8FBD95CA8 /* PBXContainerItemProxy */; + }; + D6B9451245EC7F755751840A10706B3B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Protobuf; + target = 470FE31978DC918618A329D8B55C85FF /* Protobuf */; + targetProxy = 265B4CB516E1900A62F53357B2801D7D /* PBXContainerItemProxy */; + }; + D6CCD2C4CEAD112F1B79C0511A89B945 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 0E252FBA5043E82AE7E96DA6EB172D5A /* PBXContainerItemProxy */; + }; + DC9B574DFA929B605978935F3BDB7CD8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 650053CB0020B8878A2D404A11BA8849 /* PBXContainerItemProxy */; + }; + DF830C96531680BABA48C2DEBA893DA2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = A0D8BA7AAAA886E42762C6361B9E93C5 /* PBXContainerItemProxy */; + }; + E1D1984FE10DD52FB5F2B2F12B34CD23 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = BA9CC50F725C6CC259A91562DDF28E28 /* PBXContainerItemProxy */; + }; + E4A173EB136AA75485C7DD75F12B1475 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KeychainAccess; + target = 615C831BCE925ED486B225B87E44926D /* KeychainAccess */; + targetProxy = 2643B7A0DCE050B7ED6CFA33DA0F6891 /* PBXContainerItemProxy */; + }; + ECCC460C69DA33393BD4B7A85952E4A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Swiftilities; + target = E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */; + targetProxy = 43F7D12D0CBAC174D94F813DCDD5FCB4 /* PBXContainerItemProxy */; + }; + F0793E63BFABF823AEB6F71A3674DAE1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Anchorage; + target = 4607A9D579EE69C57F52971930107170 /* Anchorage */; + targetProxy = 79EEB88422FF194A2426408E288FCAA8 /* PBXContainerItemProxy */; + }; + F7AB0C563506FE1FE6520F4C7180C61E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Swiftilities; + target = E7C4F2B07D36F87501AA418B0A2B9B20 /* Swiftilities */; + targetProxy = 92AABBA7207468A376E84C3CAB584DF1 /* PBXContainerItemProxy */; + }; + F9A75F4BC4D33D1F83CBE160AE2D088A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = D10A23904F9F6203C441116CC0642596 /* PBXContainerItemProxy */; + }; + F9BEA3D05D836C128E1EDBBAFDABF6FA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Alamofire; + target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */; + targetProxy = 2871C78E72BACE3957C7839A26C5C9E2 /* PBXContainerItemProxy */; + }; + FB6BFA54D8E0043795CCFBF57526DAC9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = 39C2E1ACB757D961A3B5FA5055DBDB7A /* PBXContainerItemProxy */; + }; + FE3F8C74A60E5614770271527A3085D9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sourcery; + target = 4D8229B0397AE8C2F7C11B3F9EFC9362 /* Sourcery */; + targetProxy = 9DE5315A218DF3035FAB4B2C9C4D11CB /* PBXContainerItemProxy */; + }; + FE817F57A0DB193392689548BF3A3052 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalyticsInterop; + target = D372E53E2E8FEAA06A0439FB85E65767 /* FirebaseAnalyticsInterop */; + targetProxy = 0C1025B53BD27B110B05E793A41AAC91 /* PBXContainerItemProxy */; + }; + FEB053648A54BC05E6A6BD49CB6EFFB8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 635675962B01177CB052EE57060E9175 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00EB2E82A5B0B8A56724F99E9E52E4D1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0254BAE7CE7FF9132CED803AB907108A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 039EE3DB7B81592FA54E996A2FA0ADA2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 04A03498AB90701059293AFCA227A006 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 04A2E9C489820651DDD7EBB81053B7F6 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 04B18C7BB734A96B78663C803082150E /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 518BACD57DCD1AA45BE9270B8C5CF1B5 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.sprint.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 0713FE5CA23092328690CD5EB985282E /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3CE8A623704EA768F5F5576533B75CC4 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.appstore.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 0D8464153D08FF29E320719CA18CC762 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0F25A9D4FB36C7AEE76E082640AEB849 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0F4EC60DB5AAAD234EFA6B150F815685 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 1051691A092C7F9BF7A92E2499457D71 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 1199DB3A26F46619A4FCEC8A16240B6F /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FA50610602A727B99D7294CFF81CC8E8 /* Pods-Services.sprint.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 11F9092E77544F230B698CEBAE36F056 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 12B0D6060B6FDC7B09FFA077EAF0B6D9 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 144971CF95B2CD5FCA86ABF5BADCB555 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 14E8B325593A0C460C587178B7C532D0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 159D225BF64246DF8997FEA3CA3EC301 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 17CDC4C0F8D77EC8C6301E0F603D7B15 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 18CA8C893BCBE6F8D77C5A5AEE2E3C5A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 196DFA3E4A09A28224918543529A1885 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 1B568D5E7B586B33C7A6283DFCD7471A /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 1B8E2F83D29A7E155F9C0D7667985900 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1C8A0A6F4C5F5B881F1EFBF4871CD760 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FCBFF9345F652100273AE93760F66435 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.develop.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 1CFF61CD09FAF75F0BC682385BFCFFF6 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 1EE499CAA9B9A581F734CFAF6A89AE21 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 1EF59DD9196C67C2E74F889C3D4F0688 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4C3439A40A51D1DD58761BACB9331DD2 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.develop.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 2100E3A23E09BC4C1BF0048C9EAD2668 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2822158D7FB1BA237200334E1B16A5C6 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 2A7F38D1EF8B29D489C3832351159F23 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 2C0B45A6DDB4DBDF13F8CE92C38F53C1 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 2C6C1ADA1F07A8A724FC6FA8DE0D080C /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 2C7C989247E976CB9C619585E7ED8A3D /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 2E0BAC58EBC4FC3F5FD6C17B54A79FCE /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 2E1070759DFCEAE5DBC3D05A79D21818 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 2EBE7AF5528F4B0A2979A4F75E2B7455 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3050D30F799954B1E665C3A7680DD3B0 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 3081CFAE229FA4D87A8A3E02E6DCA7CE /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 32DF797FC2BA977E48213B2D2905F94E /* AppStore */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_APP_STORE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = AppStore; + }; + 35AA0B11D35AF3095628DA85C865C8F9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 364397E9C482719315F8047008C221D2 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1358F7B95EC32C0D0017CE9DBF481067 /* Pods-Services.develop.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 39AF457727CE54F1468C1931870EE8D7 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 3B2882C18947648D49623DE63CD7878B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 3BC5A964067AEDB034176E8C2BB6E7FF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 408553D5662ECD01C20BEEAE8476A0C7 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 41270F5C2928C3228E603B006F90F1CC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 42E49BF53D9157BB9344A2CC526BACC5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 450810C364F1E1DDF83105C03CE8BC36 /* Develop */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEVELOP=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Develop; + }; + 49766F900A5C72F44F481929BA94E8DD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 499E3B22BACADD3B8477C76F94E244B6 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4E20B0FBC288B4FD517A0DF3FB456E2C /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 509B26019E80E3850DC661C59B808AEC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 53551413403BE972D3E8493F09D2C8FD /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 550B6A298227661823F1F5C8EAC12E56 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 552B962A72956A32E1115D1EABC2E9F5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 55D765C25ECE04A06B8472EF8DFC9DFD /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 56D6E34BB3BA305D4FA7DE8351D15A46 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 5E16DF94949DE370FF8D05B1E045B422 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 5F5BCFAB1070EDB4201DFE7442682AE2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 61AD3E65B684B8E73656F0D56E018E29 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 633FC423F2340EFA2707DC27384F9758 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6359B27DDFBAAE66820844B7D3BF1FA5 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 63ECAB3994BFB9748CC59B38CADC7DB3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6695784FCCABB730014805A0EB284E5C /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + 669A20526B876F22A3CB86ACBB325D48 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 68A8D49864B3832FE56A43ED9B1B123F /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 6962A61309DC47EF9A575651A2398BE5 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 69676CF0BD63662A543E125C1388DA3B /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 6B730C2AD0DC9F84451A95E0ED36711E /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 6F7C956FBBCA91ECDF34F5C9E200B32F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 7020CBA8E19C4B6CF917293F57A0F527 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 71D5922172D4BD46D1AC0DD998152A48 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + 726AAC41D2598F544BCCD63B8F121641 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 300E24828164112EB400CCFD1E0D55B9 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 74A377298A7D8A87145937AF5D80DCE8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 74F5C40245ED34AFFCCF455D62178E4D /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 767863B65D92FB2CB2EE44143C7E2DFC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 76B98C1F7279585A3DD4518B7A92A3F3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7786C4C4E9915070055DB93D1913AC43 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 787131EB6F6B472B14334B443B8ABEFE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 78C9F0FA9EF8EDD145018C7274250F50 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D8EF06309EC41CEC3AF331AB6DB7878 /* SimulatorStatusMagic.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SimulatorStatusMagic/SimulatorStatusMagic.modulemap"; + PRODUCT_MODULE_NAME = SimulatorStatusMagic; + PRODUCT_NAME = SimulatorStatusMagic; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7A77DF826D098FF294E4863DAE59DCF5 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 7ED7514A62123D5D92584EA8C9C37C39 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8CC134AECB569C629CF74E270D3E8FC3 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7F5387FAE75904C8004C212967CB3D9E /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 85AD63334D8D13A60DFE0BB1071985A1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 88BE0DFE71CC7168CFCC5C94FD68FBAF /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Sprint; + }; + 88F1D88DE44D2B31391FB31F87F5420B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 897DF11BAB21990629273F4ED92C4BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8D4E8064A6E1AE1BC3059CDADAC6099B /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + 8F096FFE8BE74F303E264B15215402F7 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 90EE269E3843AE0436AE918C0F54059F /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + 92961265545DD48C54C580534E52CF68 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 953BC77CB9790C62A92DF0A2929FF3C5 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 96C74D5221D5814C2CE57E69013C3960 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4828B56C5B80523897F6CBDD5D3B3A9 /* Fabric.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + 9965E55FC4DECB0117079BD67CF8878D /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B615DF0A4E2594338ED481B11588D58 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 9C70C99294CC907784B8B046DEE5ADD0 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + 9D93C1F0F78F34A3C48E2A6B55563C65 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9DA51A607CE00DD6264E22148850D773 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; + }; + name = AppStore; + }; + 9F69C0A0AB91255C0692BB69E36686D0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 9F8B0E054D88C9FC8917BBFBC1360620 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A041F186FE50D9877B5819916FDF0566 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + A06DBFB160B14C3FA503AA03B81A725E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A5A6C84A12A24B5A0FE3506327BC97B0 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + A68E4364E8E879D0CCC3B774083C68DF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + AA7077CCF0F64B5EA73E673F2B07AFD2 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + AA7597AE20A25CD48F28517DA043BBD2 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE844136E9565381DCE5C5F9351C471F /* Swiftilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Swiftilities/Swiftilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Swiftilities/Swiftilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Swiftilities/Swiftilities.modulemap"; + PRODUCT_MODULE_NAME = Swiftilities; + PRODUCT_NAME = Swiftilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + AAA519652BFF7D297098BD1231DEC00E /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + ABCAE6CDB3895468DB3C480224431DFC /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + AD8485FE4FD0FA44414D0D3ECB167981 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + AE124D04BF3E399310B7C68FF9701F9A /* Sprint */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_SPRINT=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Sprint; + }; + AF1DF8E0128E062AE69D83B2532AAD7E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + B22756789FA9D2660AA73FDE4B8229FE /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44FAF16BCF5B6BAF49B600E1705BDDA8 /* OHHTTPStubs.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap"; + PRODUCT_MODULE_NAME = OHHTTPStubs; + PRODUCT_NAME = OHHTTPStubs; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + B35D9CD99D8A25AB4414B3B709AC720A /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BD73765D65D2C624A111458E58A5B65 /* Sourcery.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + B44E2B38C771C5A2C004CA70C1C2B036 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6B5EE9E127E1998FA1E68B6FDE3320E /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + B842C542B2D62DF3B418AA5CF63FC75E /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CCFD57B4855E47C75085F7EE2C0C26F /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + BECCEE3147E15EC5BB626D63AEDA427C /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + C0CC21FC535B013F47BA834C17EDE971 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + C116202B204AD641474621E4DD1EFD8C /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Sprint; + }; + C34442325BC613212BE360E9A1B287C0 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC414D0EFF015D8E9247497DA1A0F9BA /* SwiftGen.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + C3EDB0EF10720D252471E621F18A22C6 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1B8FB54E04E0BCE999A1D682113076BC /* Instabug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C79E87935912A6EDADF557045121C2FB /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + C88F9D7AE9397281737BE3E4368E6A2E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D08D01F4ECD4EACABAFFDA7D8BF8C650 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D145A3500A16BD3C2F77656477C0973A /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E54870959F59F22BCB08CA4167583986 /* Protobuf.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Protobuf/Protobuf-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Protobuf/Protobuf-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Protobuf/Protobuf.modulemap"; + PRODUCT_MODULE_NAME = Protobuf; + PRODUCT_NAME = Protobuf; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + D1529A02A55F2EB4E938DAF6F814198A /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 41F274F617604ED563383627B85827DC /* FirebaseAnalyticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + D35CA734DD619ED347BD1DF725F3EC63 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B5EB7B674973D5CE40A58AE31AC92E9B /* Alamofire.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap"; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = Alamofire; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + D43D4960BF9B5B2EE70F2E74AC781C23 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1987EE9FAD1DBEC74F2716EA5DC6B2D0 /* Pods-Services.appstore.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + D507D5924E1956DD46D4CEA4A90B6809 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + D793ADAD0EC3994198BEAC0EFD3A4201 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAE3AF6A2BFD0F7982AA355EC9BE292 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D799CBBECD2761D3D5D077351D4506EB /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C4B85119F40EE2D53CF9459420F29B53 /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}.appstore.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}/Pods-{{ cookiecutter.project_name | replace(' ', '') }}.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + DAAA5A6195EA66DEF295EFDB8229C517 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DC8D8A01840CF56E0D9F579AE919ED3D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DE31AB1501D6E1FCABBA192529BE687A /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F59AE9C0D385B85CEB307FB212B97D8 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + E147BD630EF0E4454A1C5C8DA27B8289 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7B31944D9854B90AB402DAEBC2714BCB /* Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.sprint.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests/Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + E29E38B22BBE23E680601EB9B01F8761 /* Sprint */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC7F13FCD9B838BB5D7FE97FA10E198B /* KeychainAccess.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KeychainAccess/KeychainAccess-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KeychainAccess/KeychainAccess-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KeychainAccess/KeychainAccess.modulemap"; + PRODUCT_MODULE_NAME = KeychainAccess; + PRODUCT_NAME = KeychainAccess; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Sprint; + }; + E4B02B37D44325E20D374DCD3C7C229B /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E8B36E9487BF0AD67225C66D4BDF91E /* BonMot.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/BonMot/BonMot-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/BonMot/BonMot-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/BonMot/BonMot.modulemap"; + PRODUCT_MODULE_NAME = BonMot; + PRODUCT_NAME = BonMot; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + E6F928BAAFE49B0BFF922CB775A36876 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D732D5D9559EDA442717B3169D1CD02A /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + EA88E206F53F5B0170EA50A9EBDAAF07 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A76A5F4D0E5F82D9FC00DA6EB9ECEB7 /* Anchorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Anchorage/Anchorage-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Anchorage/Anchorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Anchorage/Anchorage.modulemap"; + PRODUCT_MODULE_NAME = Anchorage; + PRODUCT_NAME = Anchorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = AppStore; + }; + EBC0241E2EDBDD9DCB253CCC4A4C250F /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334FDF774DD8D0F228218C3AC4022462 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + EE9B60D8F1FED00BC5D55D35C2B67C86 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 63202DA0FE6824272136B2EC50F9FB63 /* Pods-Services.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Services/Pods-Services-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Services/Pods-Services.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + F0BB655AF6A9EBC59E21E9AD77EA7155 /* AppStore */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0671265B9FE7DF38216F076BB46909D0 /* SwiftLint.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = AppStore; + }; + F13196A4950243EBC6D7E5A7CE023F74 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + F330ABE5447C3B8163B50A33CD693F7B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F8EE708210187D87C395FFAB338FB6D6 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1F330F3CA48542BD6A9C003C0933FA9 /* FirebaseMessaging.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseMessaging/FirebaseMessaging.modulemap"; + PRODUCT_MODULE_NAME = FirebaseMessaging; + PRODUCT_NAME = FirebaseMessaging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Develop; + }; + FC1A59A202CBA257ABFB40043E669367 /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D98BBE0C5FC01EFB26B8F799555129 /* Crashlytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Develop; + }; + FF90010BB3F5E1134B46DE5DA1CCB64E /* Develop */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55833793A0E8B80874C88684CE1633C9 /* AppCenter.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppCenter"; + INFOPLIST_FILE = "Target Support Files/AppCenter/ResourceBundle-AppCenterDistributeResources-AppCenter-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = AppCenterDistributeResources; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Develop; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0A1FEBE926726C9A3E064BDC1F0E7D33 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F0BB655AF6A9EBC59E21E9AD77EA7155 /* AppStore */, + 2EBE7AF5528F4B0A2979A4F75E2B7455 /* Debug */, + 1B568D5E7B586B33C7A6283DFCD7471A /* Develop */, + DC8D8A01840CF56E0D9F579AE919ED3D /* Release */, + 2C6C1ADA1F07A8A724FC6FA8DE0D080C /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0BD4EFF72DD4194F3E6290A1EAE82CBC /* Build configuration list for PBXAggregateTarget "Firebase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3050D30F799954B1E665C3A7680DD3B0 /* AppStore */, + D08D01F4ECD4EACABAFFDA7D8BF8C650 /* Debug */, + EBC0241E2EDBDD9DCB253CCC4A4C250F /* Develop */, + 2100E3A23E09BC4C1BF0048C9EAD2668 /* Release */, + 8D4E8064A6E1AE1BC3059CDADAC6099B /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 14608CC6B8CF27B7AF9B3D5F5B6F8607 /* Build configuration list for PBXAggregateTarget "SwiftGen" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C34442325BC613212BE360E9A1B287C0 /* AppStore */, + 9F69C0A0AB91255C0692BB69E36686D0 /* Debug */, + A5A6C84A12A24B5A0FE3506327BC97B0 /* Develop */, + 7020CBA8E19C4B6CF917293F57A0F527 /* Release */, + C116202B204AD641474621E4DD1EFD8C /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1B3AA62DD852E489C6FA81F9BAE7F98C /* Build configuration list for PBXNativeTarget "OHHTTPStubs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B22756789FA9D2660AA73FDE4B8229FE /* AppStore */, + 897DF11BAB21990629273F4ED92C4BE5 /* Debug */, + 90EE269E3843AE0436AE918C0F54059F /* Develop */, + A68E4364E8E879D0CCC3B774083C68DF /* Release */, + 5E16DF94949DE370FF8D05B1E045B422 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 44BF99169533508633331B4E79AD527F /* Build configuration list for PBXAggregateTarget "Fabric" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96C74D5221D5814C2CE57E69013C3960 /* AppStore */, + 63ECAB3994BFB9748CC59B38CADC7DB3 /* Debug */, + 6695784FCCABB730014805A0EB284E5C /* Develop */, + 14E8B325593A0C460C587178B7C532D0 /* Release */, + 669A20526B876F22A3CB86ACBB325D48 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 47242F938FAF8F33076BEC83B73F1607 /* Build configuration list for PBXNativeTarget "Alamofire" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 71D5922172D4BD46D1AC0DD998152A48 /* AppStore */, + 41270F5C2928C3228E603B006F90F1CC /* Debug */, + 1EE499CAA9B9A581F734CFAF6A89AE21 /* Develop */, + 159D225BF64246DF8997FEA3CA3EC301 /* Release */, + D35CA734DD619ED347BD1DF725F3EC63 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 32DF797FC2BA977E48213B2D2905F94E /* AppStore */, + 196DFA3E4A09A28224918543529A1885 /* Debug */, + 450810C364F1E1DDF83105C03CE8BC36 /* Develop */, + B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */, + AE124D04BF3E399310B7C68FF9701F9A /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4964BEA93FE393CBB81F0EB03B4B3C81 /* Build configuration list for PBXNativeTarget "Pods-{{ cookiecutter.project_name | replace(' ', '') }}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D799CBBECD2761D3D5D077351D4506EB /* AppStore */, + 7ED7514A62123D5D92584EA8C9C37C39 /* Debug */, + 1EF59DD9196C67C2E74F889C3D4F0688 /* Develop */, + 18CA8C893BCBE6F8D77C5A5AEE2E3C5A /* Release */, + 04B18C7BB734A96B78663C803082150E /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 590CEAC43BDDFAA9598150F9D23A62A1 /* Build configuration list for PBXAggregateTarget "FirebaseAnalyticsInterop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8F096FFE8BE74F303E264B15215402F7 /* AppStore */, + 1B8E2F83D29A7E155F9C0D7667985900 /* Debug */, + D1529A02A55F2EB4E938DAF6F814198A /* Develop */, + 74A377298A7D8A87145937AF5D80DCE8 /* Release */, + 2A7F38D1EF8B29D489C3832351159F23 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 615A1A40348710AE156325FFE219FE30 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 12B0D6060B6FDC7B09FFA077EAF0B6D9 /* AppStore */, + 509B26019E80E3850DC661C59B808AEC /* Debug */, + E6F928BAAFE49B0BFF922CB775A36876 /* Develop */, + 35AA0B11D35AF3095628DA85C865C8F9 /* Release */, + 6962A61309DC47EF9A575651A2398BE5 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7C6BA1361CF9FA39E02D40A29E2613E3 /* Build configuration list for PBXNativeTarget "FirebaseMessaging" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BECCEE3147E15EC5BB626D63AEDA427C /* AppStore */, + 408553D5662ECD01C20BEEAE8476A0C7 /* Debug */, + F8EE708210187D87C395FFAB338FB6D6 /* Develop */, + C88F9D7AE9397281737BE3E4368E6A2E /* Release */, + 953BC77CB9790C62A92DF0A2929FF3C5 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 860FD77954D8865C1B7965B630EFD07E /* Build configuration list for PBXNativeTarget "Pods-{{ cookiecutter.project_name | replace(' ', '') }}-{{ cookiecutter.project_name | replace(' ', '') }}Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0713FE5CA23092328690CD5EB985282E /* AppStore */, + 726AAC41D2598F544BCCD63B8F121641 /* Debug */, + 1C8A0A6F4C5F5B881F1EFBF4871CD760 /* Develop */, + 49766F900A5C72F44F481929BA94E8DD /* Release */, + E147BD630EF0E4454A1C5C8DA27B8289 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 991E43F74ED979CF133D44C61CD0896E /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C7C989247E976CB9C619585E7ED8A3D /* AppStore */, + 633FC423F2340EFA2707DC27384F9758 /* Debug */, + DE31AB1501D6E1FCABBA192529BE687A /* Develop */, + 9D93C1F0F78F34A3C48E2A6B55563C65 /* Release */, + 7A77DF826D098FF294E4863DAE59DCF5 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 994CC284732864C1FB83DEFEECB2939B /* Build configuration list for PBXNativeTarget "Protobuf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D145A3500A16BD3C2F77656477C0973A /* AppStore */, + C79E87935912A6EDADF557045121C2FB /* Debug */, + AAA519652BFF7D297098BD1231DEC00E /* Develop */, + 3BC5A964067AEDB034176E8C2BB6E7FF /* Release */, + AD8485FE4FD0FA44414D0D3ECB167981 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 99D1947D468DCEAA4431F1F95263DC3A /* Build configuration list for PBXNativeTarget "KeychainAccess" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4E20B0FBC288B4FD517A0DF3FB456E2C /* AppStore */, + 767863B65D92FB2CB2EE44143C7E2DFC /* Debug */, + 2822158D7FB1BA237200334E1B16A5C6 /* Develop */, + 6F7C956FBBCA91ECDF34F5C9E200B32F /* Release */, + E29E38B22BBE23E680601EB9B01F8761 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A2C2BA6807BBA455470E664F6B40CF02 /* Build configuration list for PBXAggregateTarget "Crashlytics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 11F9092E77544F230B698CEBAE36F056 /* AppStore */, + F330ABE5447C3B8163B50A33CD693F7B /* Debug */, + FC1A59A202CBA257ABFB40043E669367 /* Develop */, + 039EE3DB7B81592FA54E996A2FA0ADA2 /* Release */, + 0F4EC60DB5AAAD234EFA6B150F815685 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A304035945DB998EEDDC0634D2BF9F26 /* Build configuration list for PBXNativeTarget "Swiftilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 55D765C25ECE04A06B8472EF8DFC9DFD /* AppStore */, + 787131EB6F6B472B14334B443B8ABEFE /* Debug */, + AA7597AE20A25CD48F28517DA043BBD2 /* Develop */, + A06DBFB160B14C3FA503AA03B81A725E /* Release */, + 144971CF95B2CD5FCA86ABF5BADCB555 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B345AD1AAB27ADDC33CD59391F2A2578 /* Build configuration list for PBXAggregateTarget "Sourcery" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA7077CCF0F64B5EA73E673F2B07AFD2 /* AppStore */, + 5F5BCFAB1070EDB4201DFE7442682AE2 /* Debug */, + A041F186FE50D9877B5819916FDF0566 /* Develop */, + 0D8464153D08FF29E320719CA18CC762 /* Release */, + B35D9CD99D8A25AB4414B3B709AC720A /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B7E7737163084DF0736A1DA737474EA7 /* Build configuration list for PBXAggregateTarget "Instabug" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ABCAE6CDB3895468DB3C480224431DFC /* AppStore */, + AF1DF8E0128E062AE69D83B2532AAD7E /* Debug */, + 3081CFAE229FA4D87A8A3E02E6DCA7CE /* Develop */, + C3EDB0EF10720D252471E621F18A22C6 /* Release */, + 69676CF0BD63662A543E125C1388DA3B /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C16269269CE2C3CF48FAFB11DDCA540B /* Build configuration list for PBXNativeTarget "GoogleUtilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 56D6E34BB3BA305D4FA7DE8351D15A46 /* AppStore */, + 61AD3E65B684B8E73656F0D56E018E29 /* Debug */, + 550B6A298227661823F1F5C8EAC12E56 /* Develop */, + D793ADAD0EC3994198BEAC0EFD3A4201 /* Release */, + 7786C4C4E9915070055DB93D1913AC43 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D99A31EFD5DABE8C08BD3F146933A31D /* Build configuration list for PBXNativeTarget "Anchorage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EA88E206F53F5B0170EA50A9EBDAAF07 /* AppStore */, + 552B962A72956A32E1115D1EABC2E9F5 /* Debug */, + 17CDC4C0F8D77EC8C6301E0F603D7B15 /* Develop */, + 9F8B0E054D88C9FC8917BBFBC1360620 /* Release */, + D507D5924E1956DD46D4CEA4A90B6809 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DEA17664DA1352A9AF015846F7DC4098 /* Build configuration list for PBXNativeTarget "FirebaseCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 53551413403BE972D3E8493F09D2C8FD /* AppStore */, + 76B98C1F7279585A3DD4518B7A92A3F3 /* Debug */, + 68A8D49864B3832FE56A43ED9B1B123F /* Develop */, + 2E0BAC58EBC4FC3F5FD6C17B54A79FCE /* Release */, + 9965E55FC4DECB0117079BD67CF8878D /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DF9887486229B1728B84F6155310DF6E /* Build configuration list for PBXNativeTarget "AppCenter-AppCenterDistributeResources" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DA51A607CE00DD6264E22148850D773 /* AppStore */, + F13196A4950243EBC6D7E5A7CE023F74 /* Debug */, + FF90010BB3F5E1134B46DE5DA1CCB64E /* Develop */, + 3B2882C18947648D49623DE63CD7878B /* Release */, + 88BE0DFE71CC7168CFCC5C94FD68FBAF /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E242987B250CB1C0EA9B99A80377B33E /* Build configuration list for PBXNativeTarget "SimulatorStatusMagic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2E1070759DFCEAE5DBC3D05A79D21818 /* AppStore */, + 78C9F0FA9EF8EDD145018C7274250F50 /* Debug */, + 74F5C40245ED34AFFCCF455D62178E4D /* Develop */, + 1051691A092C7F9BF7A92E2499457D71 /* Release */, + 6B730C2AD0DC9F84451A95E0ED36711E /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E481993470B5B9DFECE3140821C2904E /* Build configuration list for PBXNativeTarget "nanopb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B842C542B2D62DF3B418AA5CF63FC75E /* AppStore */, + 00EB2E82A5B0B8A56724F99E9E52E4D1 /* Debug */, + 1CFF61CD09FAF75F0BC682385BFCFFF6 /* Develop */, + 92961265545DD48C54C580534E52CF68 /* Release */, + 9C70C99294CC907784B8B046DEE5ADD0 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EBAF0176DA76634D02397BD80DC087AD /* Build configuration list for PBXNativeTarget "BonMot" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C0B45A6DDB4DBDF13F8CE92C38F53C1 /* AppStore */, + 499E3B22BACADD3B8477C76F94E244B6 /* Debug */, + E4B02B37D44325E20D374DCD3C7C229B /* Develop */, + 85AD63334D8D13A60DFE0BB1071985A1 /* Release */, + 7F5387FAE75904C8004C212967CB3D9E /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EF7E77D70CE9CA6FA1C9D136EC7A4F62 /* Build configuration list for PBXAggregateTarget "AppCenter" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 04A2E9C489820651DDD7EBB81053B7F6 /* AppStore */, + 42E49BF53D9157BB9344A2CC526BACC5 /* Debug */, + 04A03498AB90701059293AFCA227A006 /* Develop */, + 0F25A9D4FB36C7AEE76E082640AEB849 /* Release */, + C0CC21FC535B013F47BA834C17EDE971 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F7527E454CF938C5B4E80CDBBF13A340 /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 39AF457727CE54F1468C1931870EE8D7 /* AppStore */, + 0254BAE7CE7FF9132CED803AB907108A /* Debug */, + 6359B27DDFBAAE66820844B7D3BF1FA5 /* Develop */, + 88F1D88DE44D2B31391FB31F87F5420B /* Release */, + B44E2B38C771C5A2C004CA70C1C2B036 /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F8BFF7D89DB99B737428DD3707FD5D7B /* Build configuration list for PBXNativeTarget "Pods-Services" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D43D4960BF9B5B2EE70F2E74AC781C23 /* AppStore */, + EE9B60D8F1FED00BC5D55D35C2B67C86 /* Debug */, + 364397E9C482719315F8047008C221D2 /* Develop */, + DAAA5A6195EA66DEF295EFDB8229C517 /* Release */, + 1199DB3A26F46619A4FCEC8A16240B6F /* Sprint */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/LICENSE new file mode 100644 index 0000000..19b305b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/LICENSE @@ -0,0 +1,32 @@ +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/README.md new file mode 100644 index 0000000..f622956 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/README.md @@ -0,0 +1,85 @@ +Protocol Buffers - Google's data interchange format +=================================================== + +Copyright 2008 Google Inc. + +https://developers.google.com/protocol-buffers/ + +Overview +-------- + +Protocol Buffers (a.k.a., protobuf) are Google's language-neutral, +platform-neutral, extensible mechanism for serializing structured data. You +can find [protobuf's documentation on the Google Developers site](https://developers.google.com/protocol-buffers/). + +This README file contains protobuf installation instructions. To install +protobuf, you need to install the protocol compiler (used to compile .proto +files) and the protobuf runtime for your chosen programming language. + +Protocol Compiler Installation +------------------------------ + +The protocol compiler is written in C++. If you are using C++, please follow +the [C++ Installation Instructions](src/README.md) to install protoc along +with the C++ runtime. + +For non-C++ users, the simplest way to install the protocol compiler is to +download a pre-built binary from our release page: + + [https://github.com/protocolbuffers/protobuf/releases](https://github.com/protocolbuffers/protobuf/releases) + +In the downloads section of each release, you can find pre-built binaries in +zip packages: protoc-$VERSION-$PLATFORM.zip. It contains the protoc binary +as well as a set of standard .proto files distributed along with protobuf. + +If you are looking for an old version that is not available in the release +page, check out the maven repo here: + + [https://repo1.maven.org/maven2/com/google/protobuf/protoc/](https://repo1.maven.org/maven2/com/google/protobuf/protoc/) + +These pre-built binaries are only provided for released versions. If you want +to use the github master version at HEAD, or you need to modify protobuf code, +or you are using C++, it's recommended to build your own protoc binary from +source. + +If you would like to build protoc binary from source, see the [C++ Installation +Instructions](src/README.md). + +Protobuf Runtime Installation +----------------------------- + +Protobuf supports several different programming languages. For each programming +language, you can find instructions in the corresponding source directory about +how to install protobuf runtime for that specific language: + +| Language | Source | Ubuntu | MacOS | Windows | +|--------------------------------------|-------------------------------------------------------------|--------|-------|---------| +| C++ (include C++ runtime and protoc) | [src](src) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) | +| Java | [java](java) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_jdk7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_jdk7%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_oracle7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_oracle7%2Fcontinuous) | | | +| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous) | | +| Objective-C | [objectivec](objectivec) | | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) | | +| C# | [csharp](csharp) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) | +| JavaScript | [js](js) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | | +| Ruby | [ruby](ruby) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby25%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby25%2Fcontinuous) | | +| Go | [golang/protobuf](https://github.com/golang/protobuf) | | | | +| PHP | [php](php) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-php_all.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fphp_all%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-32-bit.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2F32-bit%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php5.6_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp5.6_mac%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php7.0_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp7.0_mac%2Fcontinuous) | | +| Dart | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) | [![Build Status](https://travis-ci.org/dart-lang/protobuf.svg?branch=master)](https://travis-ci.org/dart-lang/protobuf) | | | + +Quick Start +----------- + +The best way to learn how to use protobuf is to follow the tutorials in our +developer guide: + +https://developers.google.com/protocol-buffers/docs/tutorials + +If you want to learn from code examples, take a look at the examples in the +[examples](examples) directory. + +Documentation +------------- + +The complete documentation for Protocol Buffers is available via the +web at: + +https://developers.google.com/protocol-buffers/ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray.h new file mode 100644 index 0000000..3d22cb8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray.h @@ -0,0 +1,1967 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +//%PDDM-EXPAND DECLARE_ARRAYS() +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 + +/** + * Class used for repeated fields of int32_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBInt32Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBInt32Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBInt32Array with value in it. + **/ ++ (instancetype)arrayWithValue:(int32_t)value; + +/** + * Creates and initializes a GPBInt32Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBInt32Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array; + +/** + * Creates and initializes a GPBInt32Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBInt32Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBInt32Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBInt32Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const int32_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBInt32Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBInt32Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBInt32Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (int32_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(int32_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const int32_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBInt32Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - UInt32 + +/** + * Class used for repeated fields of uint32_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBUInt32Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBUInt32Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBUInt32Array with value in it. + **/ ++ (instancetype)arrayWithValue:(uint32_t)value; + +/** + * Creates and initializes a GPBUInt32Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBUInt32Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array; + +/** + * Creates and initializes a GPBUInt32Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBUInt32Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBUInt32Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBUInt32Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const uint32_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBUInt32Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBUInt32Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBUInt32Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (uint32_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(uint32_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const uint32_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBUInt32Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Int64 + +/** + * Class used for repeated fields of int64_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBInt64Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBInt64Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBInt64Array with value in it. + **/ ++ (instancetype)arrayWithValue:(int64_t)value; + +/** + * Creates and initializes a GPBInt64Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBInt64Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array; + +/** + * Creates and initializes a GPBInt64Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBInt64Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBInt64Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBInt64Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const int64_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBInt64Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBInt64Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBInt64Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (int64_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(int64_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const int64_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBInt64Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - UInt64 + +/** + * Class used for repeated fields of uint64_t values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64Array : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBUInt64Array. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBUInt64Array with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBUInt64Array with value in it. + **/ ++ (instancetype)arrayWithValue:(uint64_t)value; + +/** + * Creates and initializes a GPBUInt64Array with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBUInt64Array with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array; + +/** + * Creates and initializes a GPBUInt64Array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBUInt64Array with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBUInt64Array. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBUInt64Array with a copy of the values. + **/ +- (instancetype)initWithValues:(const uint64_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBUInt64Array with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBUInt64Array *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBUInt64Array with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (uint64_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(uint64_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const uint64_t [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBUInt64Array *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Float + +/** + * Class used for repeated fields of float values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBFloatArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBFloatArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBFloatArray with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBFloatArray with value in it. + **/ ++ (instancetype)arrayWithValue:(float)value; + +/** + * Creates and initializes a GPBFloatArray with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBFloatArray with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array; + +/** + * Creates and initializes a GPBFloatArray with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBFloatArray with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBFloatArray. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBFloatArray with a copy of the values. + **/ +- (instancetype)initWithValues:(const float [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBFloatArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBFloatArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBFloatArray with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (float)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(float)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const float [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBFloatArray *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(float)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Double + +/** + * Class used for repeated fields of double values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBDoubleArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBDoubleArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBDoubleArray with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBDoubleArray with value in it. + **/ ++ (instancetype)arrayWithValue:(double)value; + +/** + * Creates and initializes a GPBDoubleArray with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBDoubleArray with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array; + +/** + * Creates and initializes a GPBDoubleArray with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBDoubleArray with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBDoubleArray. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBDoubleArray with a copy of the values. + **/ +- (instancetype)initWithValues:(const double [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBDoubleArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBDoubleArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBDoubleArray with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (double)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(double)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const double [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBDoubleArray *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(double)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Bool + +/** + * Class used for repeated fields of BOOL values. This performs better than + * boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * @return A newly instanced and empty GPBBoolArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBBoolArray with the single element given. + * + * @param value The value to be placed in the array. + * + * @return A newly instanced GPBBoolArray with value in it. + **/ ++ (instancetype)arrayWithValue:(BOOL)value; + +/** + * Creates and initializes a GPBBoolArray with the contents of the given + * array. + * + * @param array Array with the contents to be put into the new array. + * + * @return A newly instanced GPBBoolArray with the contents of array. + **/ ++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array; + +/** + * Creates and initializes a GPBBoolArray with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBBoolArray with a capacity of count. + **/ ++ (instancetype)arrayWithCapacity:(NSUInteger)count; + +/** + * @return A newly initialized and empty GPBBoolArray. + **/ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBBoolArray with a copy of the values. + **/ +- (instancetype)initWithValues:(const BOOL [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBBoolArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBBoolArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBBoolArray with a capacity of count. + **/ +- (instancetype)initWithCapacity:(NSUInteger)count; + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (BOOL)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block; + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(BOOL)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const BOOL [__nullable])values count:(NSUInteger)count; + +/** + * Adds the values from the given array to this array. + * + * @param array The array containing the elements to add to this array. + **/ +- (void)addValuesFromArray:(GPBBoolArray *)array; + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value; + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +#pragma mark - Enum + +/** + * This class is used for repeated fields of int32_t values. This performs + * better than boxing into NSNumbers in NSArrays. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBEnumArray : NSObject + +/** The number of elements contained in the array. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * @return A newly instanced and empty GPBEnumArray. + **/ ++ (instancetype)array; + +/** + * Creates and initializes a GPBEnumArray with the enum validation function + * given. + * + * @param func The enum validation function for the array. + * + * @return A newly instanced GPBEnumArray. + **/ ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Creates and initializes a GPBEnumArray with the enum validation function + * given and the single raw value given. + * + * @param func The enum validation function for the array. + * @param value The raw value to add to this array. + * + * @return A newly instanced GPBEnumArray. + **/ ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValue:(int32_t)value; + +/** + * Creates and initializes a GPBEnumArray that adds the elements from the + * given array. + * + * @param array Array containing the values to add to the new array. + * + * @return A newly instanced GPBEnumArray. + **/ ++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array; + +/** + * Creates and initializes a GPBEnumArray with the given enum validation + * function and with the givencapacity. + * + * @param func The enum validation function for the array. + * @param count The capacity needed for the array. + * + * @return A newly instanced GPBEnumArray with a capacity of count. + **/ ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)count; + +/** + * Initializes the array with the given enum validation function. + * + * @param func The enum validation function for the array. + * + * @return A newly initialized GPBEnumArray with a copy of the values. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + NS_DESIGNATED_INITIALIZER; + +/** + * Initializes the array, copying the given values. + * + * @param func The enum validation function for the array. + * @param values An array with the values to put inside this array. + * @param count The number of elements to copy into the array. + * + * @return A newly initialized GPBEnumArray with a copy of the values. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + count:(NSUInteger)count; + +/** + * Initializes the array, copying the given values. + * + * @param array An array with the values to put inside this array. + * + * @return A newly initialized GPBEnumArray with a copy of the values. + **/ +- (instancetype)initWithValueArray:(GPBEnumArray *)array; + +/** + * Initializes the array with the given capacity. + * + * @param func The enum validation function for the array. + * @param count The capacity needed for the array. + * + * @return A newly initialized GPBEnumArray with a capacity of count. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)count; + +// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a +// valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value at the given index. + * + * @param index The index of the value to get. + * + * @return The value at the given index. + **/ +- (int32_t)valueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +// These methods bypass the validationFunc to provide access to values that were not +// known at the time the binary was compiled. + +/** + * Gets the raw enum value at the given index. + * + * @param index The index of the raw enum value to get. + * + * @return The raw enum value at the given index. + **/ +- (int32_t)rawValueAtIndex:(NSUInteger)index; + +/** + * Enumerates the values on this array with the given block. + * + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +/** + * Enumerates the values on this array with the given block. + * + * @param opts Options to control the enumeration. + * @param block The block to enumerate with. + * **value**: The current value being enumerated. + * **idx**: The index of the current value. + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Adds a value to this array. + * + * @param value The value to add to this array. + **/ +- (void)addValue:(int32_t)value; + +/** + * Adds values to this array. + * + * @param values The values to add to this array. + * @param count The number of elements to add. + **/ +- (void)addValues:(const int32_t [__nullable])values count:(NSUInteger)count; + + +/** + * Inserts a value into the given position. + * + * @param value The value to add to this array. + * @param index The index into which to insert the value. + **/ +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the value at the given index with the given value. + * + * @param index The index for which to replace the value. + * @param value The value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value; + +// These methods bypass the validationFunc to provide setting of values that were not +// known at the time the binary was compiled. + +/** + * Adds a raw enum value to this array. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param value The raw enum value to add to the array. + **/ +- (void)addRawValue:(int32_t)value; + +/** + * Adds raw enum values to this array. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param array Array containing the raw enum values to add to this array. + **/ +- (void)addRawValuesFromArray:(GPBEnumArray *)array; + +/** + * Adds raw enum values to this array. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param values Array containing the raw enum values to add to this array. + * @param count The number of raw values to add. + **/ +- (void)addRawValues:(const int32_t [__nullable])values count:(NSUInteger)count; + +/** + * Inserts a raw enum value at the given index. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param value Raw enum value to add. + * @param index The index into which to insert the value. + **/ +- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index; + +/** + * Replaces the raw enum value at the given index with the given value. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param index The index for which to replace the value. + * @param value The raw enum value to replace with. + **/ +- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value; + +// No validation applies to these methods. + +/** + * Removes the value at the given index. + * + * @param index The index of the value to remove. + **/ +- (void)removeValueAtIndex:(NSUInteger)index; + +/** + * Removes all the values from this array. + **/ +- (void)removeAll; + +/** + * Exchanges the values between the given indexes. + * + * @param idx1 The index of the first element to exchange. + * @param idx2 The index of the second element to exchange. + **/ +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2; + +@end + +//%PDDM-EXPAND-END DECLARE_ARRAYS() + +NS_ASSUME_NONNULL_END + +//%PDDM-DEFINE DECLARE_ARRAYS() +//%ARRAY_INTERFACE_SIMPLE(Int32, int32_t) +//%ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t) +//%ARRAY_INTERFACE_SIMPLE(Int64, int64_t) +//%ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t) +//%ARRAY_INTERFACE_SIMPLE(Float, float) +//%ARRAY_INTERFACE_SIMPLE(Double, double) +//%ARRAY_INTERFACE_SIMPLE(Bool, BOOL) +//%ARRAY_INTERFACE_ENUM(Enum, int32_t) + +// +// The common case (everything but Enum) +// + +//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE) +//%#pragma mark - NAME +//% +//%/** +//% * Class used for repeated fields of ##TYPE## values. This performs better than +//% * boxing into NSNumbers in NSArrays. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface GPB##NAME##Array : NSObject +//% +//%/** The number of elements contained in the array. */ +//%@property(nonatomic, readonly) NSUInteger count; +//% +//%/** +//% * @return A newly instanced and empty GPB##NAME##Array. +//% **/ +//%+ (instancetype)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the single element given. +//% * +//% * @param value The value to be placed in the array. +//% * +//% * @return A newly instanced GPB##NAME##Array with value in it. +//% **/ +//%+ (instancetype)arrayWithValue:(TYPE)value; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the contents of the given +//% * array. +//% * +//% * @param array Array with the contents to be put into the new array. +//% * +//% * @return A newly instanced GPB##NAME##Array with the contents of array. +//% **/ +//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the given capacity. +//% * +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly instanced GPB##NAME##Array with a capacity of count. +//% **/ +//%+ (instancetype)arrayWithCapacity:(NSUInteger)count; +//% +//%/** +//% * @return A newly initialized and empty GPB##NAME##Array. +//% **/ +//%- (instancetype)init NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param values An array with the values to put inside this array. +//% * @param count The number of elements to copy into the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValues:(const TYPE [__nullable])values +//% count:(NSUInteger)count; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param array An array with the values to put inside this array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Initializes the array with the given capacity. +//% * +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a capacity of count. +//% **/ +//%- (instancetype)initWithCapacity:(NSUInteger)count; +//% +//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, Basic) +//% +//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, Basic) +//% +//%@end +//% + +// +// Macros specific to Enums (to tweak their interface). +// + +//%PDDM-DEFINE ARRAY_INTERFACE_ENUM(NAME, TYPE) +//%#pragma mark - NAME +//% +//%/** +//% * This class is used for repeated fields of ##TYPE## values. This performs +//% * better than boxing into NSNumbers in NSArrays. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface GPB##NAME##Array : NSObject +//% +//%/** The number of elements contained in the array. */ +//%@property(nonatomic, readonly) NSUInteger count; +//%/** The validation function to check if the enums are valid. */ +//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; +//% +//%/** +//% * @return A newly instanced and empty GPB##NAME##Array. +//% **/ +//%+ (instancetype)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the enum validation function +//% * given. +//% * +//% * @param func The enum validation function for the array. +//% * +//% * @return A newly instanced GPB##NAME##Array. +//% **/ +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the enum validation function +//% * given and the single raw value given. +//% * +//% * @param func The enum validation function for the array. +//% * @param value The raw value to add to this array. +//% * +//% * @return A newly instanced GPB##NAME##Array. +//% **/ +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% rawValue:(TYPE)value; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array that adds the elements from the +//% * given array. +//% * +//% * @param array Array containing the values to add to the new array. +//% * +//% * @return A newly instanced GPB##NAME##Array. +//% **/ +//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Creates and initializes a GPB##NAME##Array with the given enum validation +//% * function and with the givencapacity. +//% * +//% * @param func The enum validation function for the array. +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly instanced GPB##NAME##Array with a capacity of count. +//% **/ +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% capacity:(NSUInteger)count; +//% +//%/** +//% * Initializes the array with the given enum validation function. +//% * +//% * @param func The enum validation function for the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param func The enum validation function for the array. +//% * @param values An array with the values to put inside this array. +//% * @param count The number of elements to copy into the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% rawValues:(const TYPE [__nullable])values +//% count:(NSUInteger)count; +//% +//%/** +//% * Initializes the array, copying the given values. +//% * +//% * @param array An array with the values to put inside this array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a copy of the values. +//% **/ +//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Initializes the array with the given capacity. +//% * +//% * @param func The enum validation function for the array. +//% * @param count The capacity needed for the array. +//% * +//% * @return A newly initialized GPB##NAME##Array with a capacity of count. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% capacity:(NSUInteger)count; +//% +//%// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a +//%// valid enumerator as defined by validationFunc. If the actual value is +//%// desired, use "raw" version of the method. +//% +//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, NAME) +//% +//%// These methods bypass the validationFunc to provide access to values that were not +//%// known at the time the binary was compiled. +//% +//%/** +//% * Gets the raw enum value at the given index. +//% * +//% * @param index The index of the raw enum value to get. +//% * +//% * @return The raw enum value at the given index. +//% **/ +//%- (TYPE)rawValueAtIndex:(NSUInteger)index; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param opts Options to control the enumeration. +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts +//% usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% +//%// If value is not a valid enumerator as defined by validationFunc, these +//%// methods will assert in debug, and will log in release and assign the value +//%// to the default value. Use the rawValue methods below to assign non enumerator +//%// values. +//% +//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, NAME) +//% +//%@end +//% + +//%PDDM-DEFINE ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME) +//%/** +//% * Gets the value at the given index. +//% * +//% * @param index The index of the value to get. +//% * +//% * @return The value at the given index. +//% **/ +//%- (TYPE)valueAtIndex:(NSUInteger)index; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% +//%/** +//% * Enumerates the values on this array with the given block. +//% * +//% * @param opts Options to control the enumeration. +//% * @param block The block to enumerate with. +//% * **value**: The current value being enumerated. +//% * **idx**: The index of the current value. +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts +//% usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; + +//%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME) +//%/** +//% * Adds a value to this array. +//% * +//% * @param value The value to add to this array. +//% **/ +//%- (void)addValue:(TYPE)value; +//% +//%/** +//% * Adds values to this array. +//% * +//% * @param values The values to add to this array. +//% * @param count The number of elements to add. +//% **/ +//%- (void)addValues:(const TYPE [__nullable])values count:(NSUInteger)count; +//% +//%ARRAY_EXTRA_MUTABLE_METHODS1_##HELPER_NAME(NAME, TYPE) +//%/** +//% * Inserts a value into the given position. +//% * +//% * @param value The value to add to this array. +//% * @param index The index into which to insert the value. +//% **/ +//%- (void)insertValue:(TYPE)value atIndex:(NSUInteger)index; +//% +//%/** +//% * Replaces the value at the given index with the given value. +//% * +//% * @param index The index for which to replace the value. +//% * @param value The value to replace with. +//% **/ +//%- (void)replaceValueAtIndex:(NSUInteger)index withValue:(TYPE)value; +//%ARRAY_EXTRA_MUTABLE_METHODS2_##HELPER_NAME(NAME, TYPE) +//%/** +//% * Removes the value at the given index. +//% * +//% * @param index The index of the value to remove. +//% **/ +//%- (void)removeValueAtIndex:(NSUInteger)index; +//% +//%/** +//% * Removes all the values from this array. +//% **/ +//%- (void)removeAll; +//% +//%/** +//% * Exchanges the values between the given indexes. +//% * +//% * @param idx1 The index of the first element to exchange. +//% * @param idx2 The index of the second element to exchange. +//% **/ +//%- (void)exchangeValueAtIndex:(NSUInteger)idx1 +//% withValueAtIndex:(NSUInteger)idx2; + +// +// These are hooks invoked by the above to do insert as needed. +// + +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Basic(NAME, TYPE) +//%/** +//% * Adds the values from the given array to this array. +//% * +//% * @param array The array containing the elements to add to this array. +//% **/ +//%- (void)addValuesFromArray:(GPB##NAME##Array *)array; +//% +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Basic(NAME, TYPE) +// Empty +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Enum(NAME, TYPE) +// Empty +//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Enum(NAME, TYPE) +//% +//%// These methods bypass the validationFunc to provide setting of values that were not +//%// known at the time the binary was compiled. +//% +//%/** +//% * Adds a raw enum value to this array. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param value The raw enum value to add to the array. +//% **/ +//%- (void)addRawValue:(TYPE)value; +//% +//%/** +//% * Adds raw enum values to this array. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param array Array containing the raw enum values to add to this array. +//% **/ +//%- (void)addRawValuesFromArray:(GPB##NAME##Array *)array; +//% +//%/** +//% * Adds raw enum values to this array. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param values Array containing the raw enum values to add to this array. +//% * @param count The number of raw values to add. +//% **/ +//%- (void)addRawValues:(const TYPE [__nullable])values count:(NSUInteger)count; +//% +//%/** +//% * Inserts a raw enum value at the given index. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param value Raw enum value to add. +//% * @param index The index into which to insert the value. +//% **/ +//%- (void)insertRawValue:(TYPE)value atIndex:(NSUInteger)index; +//% +//%/** +//% * Replaces the raw enum value at the given index with the given value. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param index The index for which to replace the value. +//% * @param value The raw enum value to replace with. +//% **/ +//%- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(TYPE)value; +//% +//%// No validation applies to these methods. +//% diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray.m new file mode 100644 index 0000000..5ce1e59 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray.m @@ -0,0 +1,2551 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBArray_PackagePrivate.h" + +#import "GPBMessage_PackagePrivate.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +// Mutable arrays use an internal buffer that can always hold a multiple of this elements. +#define kChunkSize 16 +#define CapacityFromCount(x) (((x / kChunkSize) + 1) * kChunkSize) + +static BOOL ArrayDefault_IsValidValue(int32_t value) { + // Anything but the bad value marker is allowed. + return (value != kGPBUnrecognizedEnumeratorValue); +} + +//%PDDM-DEFINE VALIDATE_RANGE(INDEX, COUNT) +//% if (INDEX >= COUNT) { +//% [NSException raise:NSRangeException +//% format:@"Index (%lu) beyond bounds (%lu)", +//% (unsigned long)INDEX, (unsigned long)COUNT]; +//% } +//%PDDM-DEFINE MAYBE_GROW_TO_SET_COUNT(NEW_COUNT) +//% if (NEW_COUNT > _capacity) { +//% [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)]; +//% } +//% _count = NEW_COUNT; +//%PDDM-DEFINE SET_COUNT_AND_MAYBE_SHRINK(NEW_COUNT) +//% _count = NEW_COUNT; +//% if ((NEW_COUNT + (2 * kChunkSize)) < _capacity) { +//% [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)]; +//% } + +// +// Macros for the common basic cases. +// + +//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE, FORMAT) +//%#pragma mark - NAME +//% +//%@implementation GPB##NAME##Array { +//% @package +//% TYPE *_values; +//% NSUInteger _count; +//% NSUInteger _capacity; +//%} +//% +//%@synthesize count = _count; +//% +//%+ (instancetype)array { +//% return [[[self alloc] init] autorelease]; +//%} +//% +//%+ (instancetype)arrayWithValue:(TYPE)value { +//% // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get +//% // the type correct. +//% return [[(GPB##NAME##Array*)[self alloc] initWithValues:&value count:1] autorelease]; +//%} +//% +//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array { +//% return [[(GPB##NAME##Array*)[self alloc] initWithValueArray:array] autorelease]; +//%} +//% +//%+ (instancetype)arrayWithCapacity:(NSUInteger)count { +//% return [[[self alloc] initWithCapacity:count] autorelease]; +//%} +//% +//%- (instancetype)init { +//% self = [super init]; +//% // No work needed; +//% return self; +//%} +//% +//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array { +//% return [self initWithValues:array->_values count:array->_count]; +//%} +//% +//%- (instancetype)initWithValues:(const TYPE [])values count:(NSUInteger)count { +//% self = [self init]; +//% if (self) { +//% if (count && values) { +//% _values = reallocf(_values, count * sizeof(TYPE)); +//% if (_values != NULL) { +//% _capacity = count; +//% memcpy(_values, values, count * sizeof(TYPE)); +//% _count = count; +//% } else { +//% [self release]; +//% [NSException raise:NSMallocException +//% format:@"Failed to allocate %lu bytes", +//% (unsigned long)(count * sizeof(TYPE))]; +//% } +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithCapacity:(NSUInteger)count { +//% self = [self initWithValues:NULL count:0]; +//% if (self && count) { +//% [self internalResizeToCapacity:count]; +//% } +//% return self; +//%} +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { +//% return [[GPB##NAME##Array allocWithZone:zone] initWithValues:_values count:_count]; +//%} +//% +//%ARRAY_IMMUTABLE_CORE(NAME, TYPE, , FORMAT) +//% +//%- (TYPE)valueAtIndex:(NSUInteger)index { +//%VALIDATE_RANGE(index, _count) +//% return _values[index]; +//%} +//% +//%ARRAY_MUTABLE_CORE(NAME, TYPE, , FORMAT) +//%@end +//% + +// +// Some core macros used for both the simple types and Enums. +// + +//%PDDM-DEFINE ARRAY_IMMUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% free(_values); +//% [super dealloc]; +//%} +//% +//%- (BOOL)isEqual:(id)other { +//% if (self == other) { +//% return YES; +//% } +//% if (![other isKindOfClass:[GPB##NAME##Array class]]) { +//% return NO; +//% } +//% GPB##NAME##Array *otherArray = other; +//% return (_count == otherArray->_count +//% && memcmp(_values, otherArray->_values, (_count * sizeof(TYPE))) == 0); +//%} +//% +//%- (NSUInteger)hash { +//% // Follow NSArray's lead, and use the count as the hash. +//% return _count; +//%} +//% +//%- (NSString *)description { +//% NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; +//% for (NSUInteger i = 0, count = _count; i < count; ++i) { +//% if (i == 0) { +//% [result appendFormat:@"##FORMAT##", _values[i]]; +//% } else { +//% [result appendFormat:@", ##FORMAT##", _values[i]]; +//% } +//% } +//% [result appendFormat:@" }"]; +//% return result; +//%} +//% +//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block { +//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +//%} +//% +//%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts +//% ACCESSOR_NAME$S usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block { +//% // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). +//% BOOL stop = NO; +//% if ((opts & NSEnumerationReverse) == 0) { +//% for (NSUInteger i = 0, count = _count; i < count; ++i) { +//% block(_values[i], i, &stop); +//% if (stop) break; +//% } +//% } else if (_count > 0) { +//% for (NSUInteger i = _count; i > 0; --i) { +//% block(_values[i - 1], (i - 1), &stop); +//% if (stop) break; +//% } +//% } +//%} + +//%PDDM-DEFINE MUTATION_HOOK_None() +//%PDDM-DEFINE MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, HOOK_1, HOOK_2) +//%- (void)add##ACCESSOR_NAME##Value:(TYPE)value { +//% [self add##ACCESSOR_NAME##Values:&value count:1]; +//%} +//% +//%- (void)add##ACCESSOR_NAME##Values:(const TYPE [])values count:(NSUInteger)count { +//% if (values == NULL || count == 0) return; +//%MUTATION_HOOK_##HOOK_1() NSUInteger initialCount = _count; +//% NSUInteger newCount = initialCount + count; +//%MAYBE_GROW_TO_SET_COUNT(newCount) +//% memcpy(&_values[initialCount], values, count * sizeof(TYPE)); +//% if (_autocreator) { +//% GPBAutocreatedArrayModified(_autocreator, self); +//% } +//%} +//% +//%- (void)insert##ACCESSOR_NAME##Value:(TYPE)value atIndex:(NSUInteger)index { +//%VALIDATE_RANGE(index, _count + 1) +//%MUTATION_HOOK_##HOOK_2() NSUInteger initialCount = _count; +//% NSUInteger newCount = initialCount + 1; +//%MAYBE_GROW_TO_SET_COUNT(newCount) +//% if (index != initialCount) { +//% memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(TYPE)); +//% } +//% _values[index] = value; +//% if (_autocreator) { +//% GPBAutocreatedArrayModified(_autocreator, self); +//% } +//%} +//% +//%- (void)replaceValueAtIndex:(NSUInteger)index with##ACCESSOR_NAME##Value:(TYPE)value { +//%VALIDATE_RANGE(index, _count) +//%MUTATION_HOOK_##HOOK_2() _values[index] = value; +//%} + +//%PDDM-DEFINE ARRAY_MUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT) +//%- (void)internalResizeToCapacity:(NSUInteger)newCapacity { +//% _values = reallocf(_values, newCapacity * sizeof(TYPE)); +//% if (_values == NULL) { +//% _capacity = 0; +//% _count = 0; +//% [NSException raise:NSMallocException +//% format:@"Failed to allocate %lu bytes", +//% (unsigned long)(newCapacity * sizeof(TYPE))]; +//% } +//% _capacity = newCapacity; +//%} +//% +//%MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, None, None) +//% +//%- (void)add##ACCESSOR_NAME##ValuesFromArray:(GPB##NAME##Array *)array { +//% [self add##ACCESSOR_NAME##Values:array->_values count:array->_count]; +//%} +//% +//%- (void)removeValueAtIndex:(NSUInteger)index { +//%VALIDATE_RANGE(index, _count) +//% NSUInteger newCount = _count - 1; +//% if (index != newCount) { +//% memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(TYPE)); +//% } +//%SET_COUNT_AND_MAYBE_SHRINK(newCount) +//%} +//% +//%- (void)removeAll { +//%SET_COUNT_AND_MAYBE_SHRINK(0) +//%} +//% +//%- (void)exchangeValueAtIndex:(NSUInteger)idx1 +//% withValueAtIndex:(NSUInteger)idx2 { +//%VALIDATE_RANGE(idx1, _count) +//%VALIDATE_RANGE(idx2, _count) +//% TYPE temp = _values[idx1]; +//% _values[idx1] = _values[idx2]; +//% _values[idx2] = temp; +//%} +//% + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int32, int32_t, %d) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 + +@implementation GPBInt32Array { + @package + int32_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(int32_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBInt32Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array { + return [[(GPBInt32Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBInt32Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const int32_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(int32_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(int32_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(int32_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32Array class]]) { + return NO; + } + GPBInt32Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(int32_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%d", _values[i]]; + } else { + [result appendFormat:@", %d", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (int32_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(int32_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(int32_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(int32_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const int32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBInt32Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + int32_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t, %u) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt32 + +@implementation GPBUInt32Array { + @package + uint32_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(uint32_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBUInt32Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array { + return [[(GPBUInt32Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBUInt32Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const uint32_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(uint32_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(uint32_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(uint32_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32Array class]]) { + return NO; + } + GPBUInt32Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(uint32_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%u", _values[i]]; + } else { + [result appendFormat:@", %u", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (uint32_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(uint32_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(uint32_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(uint32_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const uint32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(uint32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBUInt32Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint32_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + uint32_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int64, int64_t, %lld) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int64 + +@implementation GPBInt64Array { + @package + int64_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(int64_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBInt64Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array { + return [[(GPBInt64Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBInt64Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const int64_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(int64_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(int64_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(int64_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64Array class]]) { + return NO; + } + GPBInt64Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(int64_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%lld", _values[i]]; + } else { + [result appendFormat:@", %lld", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (int64_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(int64_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(int64_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(int64_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const int64_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int64_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int64_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBInt64Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int64_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + int64_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t, %llu) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt64 + +@implementation GPBUInt64Array { + @package + uint64_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(uint64_t)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBUInt64Array*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array { + return [[(GPBUInt64Array*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBUInt64Array *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const uint64_t [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(uint64_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(uint64_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(uint64_t))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64Array allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64Array class]]) { + return NO; + } + GPBUInt64Array *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(uint64_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%llu", _values[i]]; + } else { + [result appendFormat:@", %llu", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (uint64_t)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(uint64_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(uint64_t))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(uint64_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const uint64_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(uint64_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint64_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBUInt64Array *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint64_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + uint64_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Float, float, %f) +// This block of code is generated, do not edit it directly. + +#pragma mark - Float + +@implementation GPBFloatArray { + @package + float *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(float)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBFloatArray*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array { + return [[(GPBFloatArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBFloatArray *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const float [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(float)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(float)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(float))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBFloatArray allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBFloatArray class]]) { + return NO; + } + GPBFloatArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(float))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%f", _values[i]]; + } else { + [result appendFormat:@", %f", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (float)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(float)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(float))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(float)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const float [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(float)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(float)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(float)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBFloatArray *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(float)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + float temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Double, double, %lf) +// This block of code is generated, do not edit it directly. + +#pragma mark - Double + +@implementation GPBDoubleArray { + @package + double *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(double)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBDoubleArray*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array { + return [[(GPBDoubleArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBDoubleArray *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const double [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(double)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(double)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(double))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBDoubleArray allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBDoubleArray class]]) { + return NO; + } + GPBDoubleArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(double))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%lf", _values[i]]; + } else { + [result appendFormat:@", %lf", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (double)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(double)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(double))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(double)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const double [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(double)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(double)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(double)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBDoubleArray *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(double)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + double temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Bool, BOOL, %d) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool + +@implementation GPBBoolArray { + @package + BOOL *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; + ++ (instancetype)array { + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)arrayWithValue:(BOOL)value { + // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get + // the type correct. + return [[(GPBBoolArray*)[self alloc] initWithValues:&value count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array { + return [[(GPBBoolArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithCapacity:count] autorelease]; +} + +- (instancetype)init { + self = [super init]; + // No work needed; + return self; +} + +- (instancetype)initWithValueArray:(GPBBoolArray *)array { + return [self initWithValues:array->_values count:array->_count]; +} + +- (instancetype)initWithValues:(const BOOL [])values count:(NSUInteger)count { + self = [self init]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(BOOL)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(BOOL)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(BOOL))]; + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)count { + self = [self initWithValues:NULL count:0]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolArray allocWithZone:zone] initWithValues:_values count:_count]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolArray class]]) { + return NO; + } + GPBBoolArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(BOOL))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%d", _values[i]]; + } else { + [result appendFormat:@", %d", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} + +- (BOOL)valueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + return _values[index]; +} + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(BOOL)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(BOOL))]; + } + _capacity = newCapacity; +} + +- (void)addValue:(BOOL)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const BOOL [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(BOOL)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(BOOL)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addValuesFromArray:(GPBBoolArray *)array { + [self addValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(BOOL)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + BOOL temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +@end + +//%PDDM-EXPAND-END (7 expansions) + +#pragma mark - Enum + +@implementation GPBEnumArray { + @package + GPBEnumValidationFunc _validationFunc; + int32_t *_values; + NSUInteger _count; + NSUInteger _capacity; +} + +@synthesize count = _count; +@synthesize validationFunc = _validationFunc; + ++ (instancetype)array { + return [[[self alloc] initWithValidationFunction:NULL] autorelease]; +} + ++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func { + return [[[self alloc] initWithValidationFunction:func] autorelease]; +} + ++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func + rawValue:(int32_t)value { + return [[[self alloc] initWithValidationFunction:func + rawValues:&value + count:1] autorelease]; +} + ++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array { + return [[(GPBEnumArray*)[self alloc] initWithValueArray:array] autorelease]; +} + ++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)count { + return [[[self alloc] initWithValidationFunction:func capacity:count] autorelease]; +} + +- (instancetype)init { + return [self initWithValidationFunction:NULL]; +} + +- (instancetype)initWithValueArray:(GPBEnumArray *)array { + return [self initWithValidationFunction:array->_validationFunc + rawValues:array->_values + count:array->_count]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + self = [super init]; + if (self) { + _validationFunc = (func != NULL ? func : ArrayDefault_IsValidValue); + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])values + count:(NSUInteger)count { + self = [self initWithValidationFunction:func]; + if (self) { + if (count && values) { + _values = reallocf(_values, count * sizeof(int32_t)); + if (_values != NULL) { + _capacity = count; + memcpy(_values, values, count * sizeof(int32_t)); + _count = count; + } else { + [self release]; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(count * sizeof(int32_t))]; + } + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)count { + self = [self initWithValidationFunction:func]; + if (self && count) { + [self internalResizeToCapacity:count]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBEnumArray allocWithZone:zone] + initWithValidationFunction:_validationFunc + rawValues:_values + count:_count]; +} + +//%PDDM-EXPAND ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d) +// This block of code is generated, do not edit it directly. + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + free(_values); + [super dealloc]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBEnumArray class]]) { + return NO; + } + GPBEnumArray *otherArray = other; + return (_count == otherArray->_count + && memcmp(_values, otherArray->_values, (_count * sizeof(int32_t))) == 0); +} + +- (NSUInteger)hash { + // Follow NSArray's lead, and use the count as the hash. + return _count; +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self]; + for (NSUInteger i = 0, count = _count; i < count; ++i) { + if (i == 0) { + [result appendFormat:@"%d", _values[i]]; + } else { + [result appendFormat:@", %d", _values[i]]; + } + } + [result appendFormat:@" }"]; + return result; +} + +- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateRawValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + if ((opts & NSEnumerationReverse) == 0) { + for (NSUInteger i = 0, count = _count; i < count; ++i) { + block(_values[i], i, &stop); + if (stop) break; + } + } else if (_count > 0) { + for (NSUInteger i = _count; i > 0; --i) { + block(_values[i - 1], (i - 1), &stop); + if (stop) break; + } + } +} +//%PDDM-EXPAND-END ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d) + +- (int32_t)valueAtIndex:(NSUInteger)index { +//%PDDM-EXPAND VALIDATE_RANGE(index, _count) +// This block of code is generated, do not edit it directly. + + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } +//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count) + int32_t result = _values[index]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + return result; +} + +- (int32_t)rawValueAtIndex:(NSUInteger)index { +//%PDDM-EXPAND VALIDATE_RANGE(index, _count) +// This block of code is generated, do not edit it directly. + + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } +//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count) + return _values[index]; +} + +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; +} + +- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { + // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). + BOOL stop = NO; + GPBEnumValidationFunc func = _validationFunc; + if ((opts & NSEnumerationReverse) == 0) { + int32_t *scan = _values; + int32_t *end = scan + _count; + for (NSUInteger i = 0; scan < end; ++i, ++scan) { + int32_t value = *scan; + if (!func(value)) { + value = kGPBUnrecognizedEnumeratorValue; + } + block(value, i, &stop); + if (stop) break; + } + } else if (_count > 0) { + int32_t *end = _values; + int32_t *scan = end + (_count - 1); + for (NSUInteger i = (_count - 1); scan >= end; --i, --scan) { + int32_t value = *scan; + if (!func(value)) { + value = kGPBUnrecognizedEnumeratorValue; + } + block(value, i, &stop); + if (stop) break; + } + } +} + +//%PDDM-EXPAND ARRAY_MUTABLE_CORE(Enum, int32_t, Raw, %d) +// This block of code is generated, do not edit it directly. + +- (void)internalResizeToCapacity:(NSUInteger)newCapacity { + _values = reallocf(_values, newCapacity * sizeof(int32_t)); + if (_values == NULL) { + _capacity = 0; + _count = 0; + [NSException raise:NSMallocException + format:@"Failed to allocate %lu bytes", + (unsigned long)(newCapacity * sizeof(int32_t))]; + } + _capacity = newCapacity; +} + +- (void)addRawValue:(int32_t)value { + [self addRawValues:&value count:1]; +} + +- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + _values[index] = value; +} + +- (void)addRawValuesFromArray:(GPBEnumArray *)array { + [self addRawValues:array->_values count:array->_count]; +} + +- (void)removeValueAtIndex:(NSUInteger)index { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + NSUInteger newCount = _count - 1; + if (index != newCount) { + memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t)); + } + _count = newCount; + if ((newCount + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } +} + +- (void)removeAll { + _count = 0; + if ((0 + (2 * kChunkSize)) < _capacity) { + [self internalResizeToCapacity:CapacityFromCount(0)]; + } +} + +- (void)exchangeValueAtIndex:(NSUInteger)idx1 + withValueAtIndex:(NSUInteger)idx2 { + if (idx1 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx1, (unsigned long)_count]; + } + if (idx2 >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)idx2, (unsigned long)_count]; + } + int32_t temp = _values[idx1]; + _values[idx1] = _values[idx2]; + _values[idx2] = temp; +} + +//%PDDM-EXPAND MUTATION_METHODS(Enum, int32_t, , EnumValidationList, EnumValidationOne) +// This block of code is generated, do not edit it directly. + +- (void)addValue:(int32_t)value { + [self addValues:&value count:1]; +} + +- (void)addValues:(const int32_t [])values count:(NSUInteger)count { + if (values == NULL || count == 0) return; + GPBEnumValidationFunc func = _validationFunc; + for (NSUInteger i = 0; i < count; ++i) { + if (!func(values[i])) { + [NSException raise:NSInvalidArgumentException + format:@"%@: Attempt to set an unknown enum value (%d)", + [self class], values[i]]; + } + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + count; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + memcpy(&_values[initialCount], values, count * sizeof(int32_t)); + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index { + if (index >= _count + 1) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count + 1]; + } + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"%@: Attempt to set an unknown enum value (%d)", + [self class], value]; + } + NSUInteger initialCount = _count; + NSUInteger newCount = initialCount + 1; + if (newCount > _capacity) { + [self internalResizeToCapacity:CapacityFromCount(newCount)]; + } + _count = newCount; + if (index != initialCount) { + memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); + } + _values[index] = value; + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value { + if (index >= _count) { + [NSException raise:NSRangeException + format:@"Index (%lu) beyond bounds (%lu)", + (unsigned long)index, (unsigned long)_count]; + } + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"%@: Attempt to set an unknown enum value (%d)", + [self class], value]; + } + _values[index] = value; +} +//%PDDM-EXPAND-END (2 expansions) + +//%PDDM-DEFINE MUTATION_HOOK_EnumValidationList() +//% GPBEnumValidationFunc func = _validationFunc; +//% for (NSUInteger i = 0; i < count; ++i) { +//% if (!func(values[i])) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"%@: Attempt to set an unknown enum value (%d)", +//% [self class], values[i]]; +//% } +//% } +//% +//%PDDM-DEFINE MUTATION_HOOK_EnumValidationOne() +//% if (!_validationFunc(value)) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"%@: Attempt to set an unknown enum value (%d)", +//% [self class], value]; +//% } +//% + +@end + +#pragma mark - NSArray Subclass + +@implementation GPBAutocreatedArray { + NSMutableArray *_array; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_array release]; + [super dealloc]; +} + +#pragma mark Required NSArray overrides + +- (NSUInteger)count { + return [_array count]; +} + +- (id)objectAtIndex:(NSUInteger)idx { + return [_array objectAtIndex:idx]; +} + +#pragma mark Required NSMutableArray overrides + +// Only need to call GPBAutocreatedArrayModified() when adding things since +// we only autocreate empty arrays. + +- (void)insertObject:(id)anObject atIndex:(NSUInteger)idx { + if (_array == nil) { + _array = [[NSMutableArray alloc] init]; + } + [_array insertObject:anObject atIndex:idx]; + + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)removeObject:(id)anObject { + [_array removeObject:anObject]; +} + +- (void)removeObjectAtIndex:(NSUInteger)idx { + [_array removeObjectAtIndex:idx]; +} + +- (void)addObject:(id)anObject { + if (_array == nil) { + _array = [[NSMutableArray alloc] init]; + } + [_array addObject:anObject]; + + if (_autocreator) { + GPBAutocreatedArrayModified(_autocreator, self); + } +} + +- (void)removeLastObject { + [_array removeLastObject]; +} + +- (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)anObject { + [_array replaceObjectAtIndex:idx withObject:anObject]; +} + +#pragma mark Extra things hooked + +- (id)copyWithZone:(NSZone *)zone { + if (_array == nil) { + return [[NSMutableArray allocWithZone:zone] init]; + } + return [_array copyWithZone:zone]; +} + +- (id)mutableCopyWithZone:(NSZone *)zone { + if (_array == nil) { + return [[NSMutableArray allocWithZone:zone] init]; + } + return [_array mutableCopyWithZone:zone]; +} + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(id __unsafe_unretained [])buffer + count:(NSUInteger)len { + return [_array countByEnumeratingWithState:state objects:buffer count:len]; +} + +- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block { + [_array enumerateObjectsUsingBlock:block]; +} + +- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block { + [_array enumerateObjectsWithOptions:opts usingBlock:block]; +} + +@end + +#pragma clang diagnostic pop diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray_PackagePrivate.h new file mode 100644 index 0000000..35a4538 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBArray_PackagePrivate.h @@ -0,0 +1,130 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBArray.h" + +@class GPBMessage; + +//%PDDM-DEFINE DECLARE_ARRAY_EXTRAS() +//%ARRAY_INTERFACE_EXTRAS(Int32, int32_t) +//%ARRAY_INTERFACE_EXTRAS(UInt32, uint32_t) +//%ARRAY_INTERFACE_EXTRAS(Int64, int64_t) +//%ARRAY_INTERFACE_EXTRAS(UInt64, uint64_t) +//%ARRAY_INTERFACE_EXTRAS(Float, float) +//%ARRAY_INTERFACE_EXTRAS(Double, double) +//%ARRAY_INTERFACE_EXTRAS(Bool, BOOL) +//%ARRAY_INTERFACE_EXTRAS(Enum, int32_t) + +//%PDDM-DEFINE ARRAY_INTERFACE_EXTRAS(NAME, TYPE) +//%#pragma mark - NAME +//% +//%@interface GPB##NAME##Array () { +//% @package +//% GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +//%} +//%@end +//% + +//%PDDM-EXPAND DECLARE_ARRAY_EXTRAS() +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 + +@interface GPBInt32Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - UInt32 + +@interface GPBUInt32Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Int64 + +@interface GPBInt64Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - UInt64 + +@interface GPBUInt64Array () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Float + +@interface GPBFloatArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Double + +@interface GPBDoubleArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Bool + +@interface GPBBoolArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Enum + +@interface GPBEnumArray () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +//%PDDM-EXPAND-END DECLARE_ARRAY_EXTRAS() + +#pragma mark - NSArray Subclass + +@interface GPBAutocreatedArray : NSMutableArray { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBBootstrap.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBBootstrap.h new file mode 100644 index 0000000..0ebca25 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBBootstrap.h @@ -0,0 +1,141 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** + * The Objective C runtime has complete enough info that most protos don’t end + * up using this, so leaving it on is no cost or very little cost. If you + * happen to see it causing bloat, this is the way to disable it. If you do + * need to disable it, try only disabling it for Release builds as having + * full TextFormat can be useful for debugging. + **/ +#ifndef GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS +#define GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS 0 +#endif + +// Used in the generated code to give sizes to enums. int32_t was chosen based +// on the fact that Protocol Buffers enums are limited to this range. +#if !__has_feature(objc_fixed_enum) + #error All supported Xcode versions should support objc_fixed_enum. +#endif + +// If the headers are imported into Objective-C++, we can run into an issue +// where the defintion of NS_ENUM (really CF_ENUM) changes based on the C++ +// standard that is in effect. If it isn't C++11 or higher, the definition +// doesn't allow us to forward declare. We work around this one case by +// providing a local definition. The default case has to use NS_ENUM for the +// magic that is Swift bridging of enums. +#if (defined(__cplusplus) && __cplusplus && __cplusplus < 201103L) + #define GPB_ENUM(X) enum X : int32_t X; enum X : int32_t +#else + #define GPB_ENUM(X) NS_ENUM(int32_t, X) +#endif + +/** + * GPB_ENUM_FWD_DECLARE is used for forward declaring enums, for example: + * + * ``` + * GPB_ENUM_FWD_DECLARE(Foo_Enum) + * + * @interface BarClass : NSObject + * @property (nonatomic) enum Foo_Enum value; + * - (void)bazMethod:(enum Foo_Enum):value; + * @end + * ``` + **/ +#define GPB_ENUM_FWD_DECLARE(X) enum X : int32_t + +/** + * Based upon CF_INLINE. Forces inlining in non DEBUG builds. + **/ +#if !defined(DEBUG) +#define GPB_INLINE static __inline__ __attribute__((always_inline)) +#else +#define GPB_INLINE static __inline__ +#endif + +/** + * For use in public headers that might need to deal with ARC. + **/ +#ifndef GPB_UNSAFE_UNRETAINED +#if __has_feature(objc_arc) +#define GPB_UNSAFE_UNRETAINED __unsafe_unretained +#else +#define GPB_UNSAFE_UNRETAINED +#endif +#endif + +/** + * Attribute used for Objective-C proto interface deprecations without messages. + **/ +#ifndef GPB_DEPRECATED +#define GPB_DEPRECATED __attribute__((deprecated)) +#endif + +/** + * Attribute used for Objective-C proto interface deprecations with messages. + **/ +#ifndef GPB_DEPRECATED_MSG +#if __has_extension(attribute_deprecated_with_message) +#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) +#else +#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated)) +#endif +#endif + +// If property name starts with init we need to annotate it to get past ARC. +// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 +// +// Meant to be used internally by generated code. +#define GPB_METHOD_FAMILY_NONE __attribute__((objc_method_family(none))) + +// ---------------------------------------------------------------------------- +// These version numbers are all internal to the ObjC Protobuf runtime; they +// are used to ensure compatibility between the generated sources and the +// headers being compiled against and/or the version of sources being run +// against. +// +// They are all #defines so the values are captured into every .o file they +// are used in and to allow comparisons in the preprocessor. + +// Current library runtime version. +// - Gets bumped when the runtime makes changes to the interfaces between the +// generated code and runtime (things added/removed, etc). +#define GOOGLE_PROTOBUF_OBJC_VERSION 30002 + +// Minimum runtime version supported for compiling/running against. +// - Gets changed when support for the older generated code is dropped. +#define GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION 30001 + + +// This is a legacy constant now frozen in time for old generated code. If +// GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION ever gets moved above 30001 then +// this should also change to break code compiled with an old runtime that +// can't be supported any more. +#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001 diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream.h new file mode 100644 index 0000000..fbe5009 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream.h @@ -0,0 +1,253 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBMessage; +@class GPBExtensionRegistry; + +NS_ASSUME_NONNULL_BEGIN + +CF_EXTERN_C_BEGIN + +/** + * @c GPBCodedInputStream exception name. Exceptions raised from + * @c GPBCodedInputStream contain an underlying error in the userInfo dictionary + * under the GPBCodedInputStreamUnderlyingErrorKey key. + **/ +extern NSString *const GPBCodedInputStreamException; + +/** The key under which the underlying NSError from the exception is stored. */ +extern NSString *const GPBCodedInputStreamUnderlyingErrorKey; + +/** NSError domain used for @c GPBCodedInputStream errors. */ +extern NSString *const GPBCodedInputStreamErrorDomain; + +/** + * Error code for NSError with @c GPBCodedInputStreamErrorDomain. + **/ +typedef NS_ENUM(NSInteger, GPBCodedInputStreamErrorCode) { + /** The size does not fit in the remaining bytes to be read. */ + GPBCodedInputStreamErrorInvalidSize = -100, + /** Attempted to read beyond the subsection limit. */ + GPBCodedInputStreamErrorSubsectionLimitReached = -101, + /** The requested subsection limit is invalid. */ + GPBCodedInputStreamErrorInvalidSubsectionLimit = -102, + /** Invalid tag read. */ + GPBCodedInputStreamErrorInvalidTag = -103, + /** Invalid UTF-8 character in a string. */ + GPBCodedInputStreamErrorInvalidUTF8 = -104, + /** Invalid VarInt read. */ + GPBCodedInputStreamErrorInvalidVarInt = -105, + /** The maximum recursion depth of messages was exceeded. */ + GPBCodedInputStreamErrorRecursionDepthExceeded = -106, +}; + +CF_EXTERN_C_END + +/** + * Reads and decodes protocol message fields. + * + * The common uses of protocol buffers shouldn't need to use this class. + * @c GPBMessage's provide a @c +parseFromData:error: and + * @c +parseFromData:extensionRegistry:error: method that will decode a + * message for you. + * + * @note Subclassing of @c GPBCodedInputStream is NOT supported. + **/ +@interface GPBCodedInputStream : NSObject + +/** + * Creates a new stream wrapping some data. + * + * @param data The data to wrap inside the stream. + * + * @return A newly instanced GPBCodedInputStream. + **/ ++ (instancetype)streamWithData:(NSData *)data; + +/** + * Initializes a stream wrapping some data. + * + * @param data The data to wrap inside the stream. + * + * @return A newly initialized GPBCodedInputStream. + **/ +- (instancetype)initWithData:(NSData *)data; + +/** + * Attempts to read a field tag, returning zero if we have reached EOF. + * Protocol message parsers use this to read tags, since a protocol message + * may legally end wherever a tag occurs, and zero is not a valid tag number. + * + * @return The field tag, or zero if EOF was reached. + **/ +- (int32_t)readTag; + +/** + * @return A double read from the stream. + **/ +- (double)readDouble; +/** + * @return A float read from the stream. + **/ +- (float)readFloat; +/** + * @return A uint64 read from the stream. + **/ +- (uint64_t)readUInt64; +/** + * @return A uint32 read from the stream. + **/ +- (uint32_t)readUInt32; +/** + * @return An int64 read from the stream. + **/ +- (int64_t)readInt64; +/** + * @return An int32 read from the stream. + **/ +- (int32_t)readInt32; +/** + * @return A fixed64 read from the stream. + **/ +- (uint64_t)readFixed64; +/** + * @return A fixed32 read from the stream. + **/ +- (uint32_t)readFixed32; +/** + * @return An enum read from the stream. + **/ +- (int32_t)readEnum; +/** + * @return A sfixed32 read from the stream. + **/ +- (int32_t)readSFixed32; +/** + * @return A fixed64 read from the stream. + **/ +- (int64_t)readSFixed64; +/** + * @return A sint32 read from the stream. + **/ +- (int32_t)readSInt32; +/** + * @return A sint64 read from the stream. + **/ +- (int64_t)readSInt64; +/** + * @return A boolean read from the stream. + **/ +- (BOOL)readBool; +/** + * @return A string read from the stream. + **/ +- (NSString *)readString; +/** + * @return Data read from the stream. + **/ +- (NSData *)readBytes; + +/** + * Read an embedded message field value from the stream. + * + * @param message The message to set fields on as they are read. + * @param extensionRegistry An optional extension registry to use to lookup + * extensions for message. + **/ +- (void)readMessage:(GPBMessage *)message + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry; + +/** + * Reads and discards a single field, given its tag value. + * + * @param tag The tag number of the field to skip. + * + * @return NO if the tag is an endgroup tag (in which case nothing is skipped), + * YES in all other cases. + **/ +- (BOOL)skipField:(int32_t)tag; + +/** + * Reads and discards an entire message. This will read either until EOF or + * until an endgroup tag, whichever comes first. + **/ +- (void)skipMessage; + +/** + * Check to see if the logical end of the stream has been reached. + * + * @note This can return NO when there is no more data, but the current parsing + * expected more data. + * + * @return YES if the logical end of the stream has been reached, NO otherwise. + **/ +- (BOOL)isAtEnd; + +/** + * @return The offset into the stream. + **/ +- (size_t)position; + +/** + * Moves the limit to the given byte offset starting at the current location. + * + * @exception GPBCodedInputStreamException If the requested bytes exceeed the + * current limit. + * + * @param byteLimit The number of bytes to move the limit, offset to the current + * location. + * + * @return The limit offset before moving the new limit. + */ +- (size_t)pushLimit:(size_t)byteLimit; + +/** + * Moves the limit back to the offset as it was before calling pushLimit:. + * + * @param oldLimit The number of bytes to move the current limit. Usually this + * is the value returned by the pushLimit: method. + */ +- (void)popLimit:(size_t)oldLimit; + +/** + * Verifies that the last call to -readTag returned the given tag value. This + * is used to verify that a nested group ended with the correct end tag. + * + * @exception NSParseErrorException If the value does not match the last tag. + * + * @param expected The tag that was expected. + **/ +- (void)checkLastTagWas:(int32_t)expected; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream.m new file mode 100644 index 0000000..57d04dd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream.m @@ -0,0 +1,505 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBCodedInputStream_PackagePrivate.h" + +#import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" +#import "GPBWireFormat.h" + +NSString *const GPBCodedInputStreamException = + GPBNSStringifySymbol(GPBCodedInputStreamException); + +NSString *const GPBCodedInputStreamUnderlyingErrorKey = + GPBNSStringifySymbol(GPBCodedInputStreamUnderlyingErrorKey); + +NSString *const GPBCodedInputStreamErrorDomain = + GPBNSStringifySymbol(GPBCodedInputStreamErrorDomain); + +// Matching: +// https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L62 +// private static final int DEFAULT_RECURSION_LIMIT = 100; +// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/io/coded_stream.cc#L86 +// int CodedInputStream::default_recursion_limit_ = 100; +static const NSUInteger kDefaultRecursionLimit = 100; + +static void RaiseException(NSInteger code, NSString *reason) { + NSDictionary *errorInfo = nil; + if ([reason length]) { + errorInfo = @{ GPBErrorReasonKey: reason }; + } + NSError *error = [NSError errorWithDomain:GPBCodedInputStreamErrorDomain + code:code + userInfo:errorInfo]; + + NSDictionary *exceptionInfo = + @{ GPBCodedInputStreamUnderlyingErrorKey: error }; + [[NSException exceptionWithName:GPBCodedInputStreamException + reason:reason + userInfo:exceptionInfo] raise]; +} + +static void CheckRecursionLimit(GPBCodedInputStreamState *state) { + if (state->recursionDepth >= kDefaultRecursionLimit) { + RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); + } +} + +static void CheckSize(GPBCodedInputStreamState *state, size_t size) { + size_t newSize = state->bufferPos + size; + if (newSize > state->bufferSize) { + RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); + } + if (newSize > state->currentLimit) { + // Fast forward to end of currentLimit; + state->bufferPos = state->currentLimit; + RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil); + } +} + +static int8_t ReadRawByte(GPBCodedInputStreamState *state) { + CheckSize(state, sizeof(int8_t)); + return ((int8_t *)state->bytes)[state->bufferPos++]; +} + +static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { + CheckSize(state, sizeof(int32_t)); + int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos); + state->bufferPos += sizeof(int32_t); + return value; +} + +static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { + CheckSize(state, sizeof(int64_t)); + int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos); + state->bufferPos += sizeof(int64_t); + return value; +} + +static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { + int32_t shift = 0; + int64_t result = 0; + while (shift < 64) { + int8_t b = ReadRawByte(state); + result |= (int64_t)((uint64_t)(b & 0x7F) << shift); + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64"); + return 0; +} + +static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { + return (int32_t)ReadRawVarint64(state); +} + +static void SkipRawData(GPBCodedInputStreamState *state, size_t size) { + CheckSize(state, size); + state->bufferPos += size; +} + +double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state) { + int64_t value = ReadRawLittleEndian64(state); + return GPBConvertInt64ToDouble(value); +} + +float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state) { + int32_t value = ReadRawLittleEndian32(state); + return GPBConvertInt32ToFloat(value); +} + +uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state) { + uint64_t value = ReadRawVarint64(state); + return value; +} + +uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state) { + uint32_t value = ReadRawVarint32(state); + return value; +} + +int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state) { + int64_t value = ReadRawVarint64(state); + return value; +} + +int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state) { + int32_t value = ReadRawVarint32(state); + return value; +} + +uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state) { + uint64_t value = ReadRawLittleEndian64(state); + return value; +} + +uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state) { + uint32_t value = ReadRawLittleEndian32(state); + return value; +} + +int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state) { + int32_t value = ReadRawVarint32(state); + return value; +} + +int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state) { + int32_t value = ReadRawLittleEndian32(state); + return value; +} + +int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state) { + int64_t value = ReadRawLittleEndian64(state); + return value; +} + +int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state) { + int32_t value = GPBDecodeZigZag32(ReadRawVarint32(state)); + return value; +} + +int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) { + int64_t value = GPBDecodeZigZag64(ReadRawVarint64(state)); + return value; +} + +BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) { + return ReadRawVarint32(state) != 0; +} + +int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { + if (GPBCodedInputStreamIsAtEnd(state)) { + state->lastTag = 0; + return 0; + } + + state->lastTag = ReadRawVarint32(state); + // Tags have to include a valid wireformat. + if (!GPBWireFormatIsValidTag(state->lastTag)) { + RaiseException(GPBCodedInputStreamErrorInvalidTag, + @"Invalid wireformat in tag."); + } + // Zero is not a valid field number. + if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) { + RaiseException(GPBCodedInputStreamErrorInvalidTag, + @"A zero field number on the wire is invalid."); + } + return state->lastTag; +} + +NSString *GPBCodedInputStreamReadRetainedString( + GPBCodedInputStreamState *state) { + int32_t size = ReadRawVarint32(state); + NSString *result; + if (size == 0) { + result = @""; + } else { + CheckSize(state, size); + result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos] + length:size + encoding:NSUTF8StringEncoding]; + state->bufferPos += size; + if (!result) { +#ifdef DEBUG + // https://developers.google.com/protocol-buffers/docs/proto#scalar + NSLog(@"UTF-8 failure, is some field type 'string' when it should be " + @"'bytes'?"); +#endif + RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil); + } + } + return result; +} + +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) { + int32_t size = ReadRawVarint32(state); + if (size < 0) return nil; + CheckSize(state, size); + NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos + length:size]; + state->bufferPos += size; + return result; +} + +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( + GPBCodedInputStreamState *state) { + int32_t size = ReadRawVarint32(state); + if (size < 0) return nil; + CheckSize(state, size); + // Cast is safe because freeWhenDone is NO. + NSData *result = [[NSData alloc] + initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos) + length:size + freeWhenDone:NO]; + state->bufferPos += size; + return result; +} + +size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, + size_t byteLimit) { + byteLimit += state->bufferPos; + size_t oldLimit = state->currentLimit; + if (byteLimit > oldLimit) { + RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil); + } + state->currentLimit = byteLimit; + return oldLimit; +} + +void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, + size_t oldLimit) { + state->currentLimit = oldLimit; +} + +size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state) { + return state->currentLimit - state->bufferPos; +} + +BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) { + return (state->bufferPos == state->bufferSize) || + (state->bufferPos == state->currentLimit); +} + +void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, + int32_t value) { + if (state->lastTag != value) { + RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read"); + } +} + +@implementation GPBCodedInputStream + ++ (instancetype)streamWithData:(NSData *)data { + return [[[self alloc] initWithData:data] autorelease]; +} + +- (instancetype)initWithData:(NSData *)data { + if ((self = [super init])) { +#ifdef DEBUG + NSCAssert([self class] == [GPBCodedInputStream class], + @"Subclassing of GPBCodedInputStream is not allowed."); +#endif + buffer_ = [data retain]; + state_.bytes = (const uint8_t *)[data bytes]; + state_.bufferSize = [data length]; + state_.currentLimit = state_.bufferSize; + } + return self; +} + +- (void)dealloc { + [buffer_ release]; + [super dealloc]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (int32_t)readTag { + return GPBCodedInputStreamReadTag(&state_); +} + +- (void)checkLastTagWas:(int32_t)value { + GPBCodedInputStreamCheckLastTagWas(&state_, value); +} + +- (BOOL)skipField:(int32_t)tag { + NSAssert(GPBWireFormatIsValidTag(tag), @"Invalid tag"); + switch (GPBWireFormatGetTagWireType(tag)) { + case GPBWireFormatVarint: + GPBCodedInputStreamReadInt32(&state_); + return YES; + case GPBWireFormatFixed64: + SkipRawData(&state_, sizeof(int64_t)); + return YES; + case GPBWireFormatLengthDelimited: + SkipRawData(&state_, ReadRawVarint32(&state_)); + return YES; + case GPBWireFormatStartGroup: + [self skipMessage]; + GPBCodedInputStreamCheckLastTagWas( + &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag), + GPBWireFormatEndGroup)); + return YES; + case GPBWireFormatEndGroup: + return NO; + case GPBWireFormatFixed32: + SkipRawData(&state_, sizeof(int32_t)); + return YES; + } +} + +- (void)skipMessage { + while (YES) { + int32_t tag = GPBCodedInputStreamReadTag(&state_); + if (tag == 0 || ![self skipField:tag]) { + return; + } + } +} + +- (BOOL)isAtEnd { + return GPBCodedInputStreamIsAtEnd(&state_); +} + +- (size_t)position { + return state_.bufferPos; +} + +- (size_t)pushLimit:(size_t)byteLimit { + return GPBCodedInputStreamPushLimit(&state_, byteLimit); +} + +- (void)popLimit:(size_t)oldLimit { + GPBCodedInputStreamPopLimit(&state_, oldLimit); +} + +- (double)readDouble { + return GPBCodedInputStreamReadDouble(&state_); +} + +- (float)readFloat { + return GPBCodedInputStreamReadFloat(&state_); +} + +- (uint64_t)readUInt64 { + return GPBCodedInputStreamReadUInt64(&state_); +} + +- (int64_t)readInt64 { + return GPBCodedInputStreamReadInt64(&state_); +} + +- (int32_t)readInt32 { + return GPBCodedInputStreamReadInt32(&state_); +} + +- (uint64_t)readFixed64 { + return GPBCodedInputStreamReadFixed64(&state_); +} + +- (uint32_t)readFixed32 { + return GPBCodedInputStreamReadFixed32(&state_); +} + +- (BOOL)readBool { + return GPBCodedInputStreamReadBool(&state_); +} + +- (NSString *)readString { + return [GPBCodedInputStreamReadRetainedString(&state_) autorelease]; +} + +- (void)readGroup:(int32_t)fieldNumber + message:(GPBMessage *)message + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + CheckRecursionLimit(&state_); + ++state_.recursionDepth; + [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; + GPBCodedInputStreamCheckLastTagWas( + &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); + --state_.recursionDepth; +} + +- (void)readUnknownGroup:(int32_t)fieldNumber + message:(GPBUnknownFieldSet *)message { + CheckRecursionLimit(&state_); + ++state_.recursionDepth; + [message mergeFromCodedInputStream:self]; + GPBCodedInputStreamCheckLastTagWas( + &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); + --state_.recursionDepth; +} + +- (void)readMessage:(GPBMessage *)message + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + CheckRecursionLimit(&state_); + int32_t length = ReadRawVarint32(&state_); + size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); + ++state_.recursionDepth; + [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; + GPBCodedInputStreamCheckLastTagWas(&state_, 0); + --state_.recursionDepth; + GPBCodedInputStreamPopLimit(&state_, oldLimit); +} + +- (void)readMapEntry:(id)mapDictionary + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + field:(GPBFieldDescriptor *)field + parentMessage:(GPBMessage *)parentMessage { + CheckRecursionLimit(&state_); + int32_t length = ReadRawVarint32(&state_); + size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); + ++state_.recursionDepth; + GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field, + parentMessage); + GPBCodedInputStreamCheckLastTagWas(&state_, 0); + --state_.recursionDepth; + GPBCodedInputStreamPopLimit(&state_, oldLimit); +} + +- (NSData *)readBytes { + return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease]; +} + +- (uint32_t)readUInt32 { + return GPBCodedInputStreamReadUInt32(&state_); +} + +- (int32_t)readEnum { + return GPBCodedInputStreamReadEnum(&state_); +} + +- (int32_t)readSFixed32 { + return GPBCodedInputStreamReadSFixed32(&state_); +} + +- (int64_t)readSFixed64 { + return GPBCodedInputStreamReadSFixed64(&state_); +} + +- (int32_t)readSInt32 { + return GPBCodedInputStreamReadSInt32(&state_); +} + +- (int64_t)readSInt64 { + return GPBCodedInputStreamReadSInt64(&state_); +} + +#pragma clang diagnostic pop + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream_PackagePrivate.h new file mode 100644 index 0000000..43ec6e7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedInputStream_PackagePrivate.h @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is private to the ProtobolBuffers library and must NOT be +// included by any sources outside this library. The contents of this file are +// subject to change at any time without notice. + +#import "GPBCodedInputStream.h" + +@class GPBUnknownFieldSet; +@class GPBFieldDescriptor; + +typedef struct GPBCodedInputStreamState { + const uint8_t *bytes; + size_t bufferSize; + size_t bufferPos; + + // For parsing subsections of an input stream you can put a hard limit on + // how much should be read. Normally the limit is the end of the stream, + // but you can adjust it to anywhere, and if you hit it you will be at the + // end of the stream, until you adjust the limit. + size_t currentLimit; + int32_t lastTag; + NSUInteger recursionDepth; +} GPBCodedInputStreamState; + +@interface GPBCodedInputStream () { + @package + struct GPBCodedInputStreamState state_; + NSData *buffer_; +} + +// Group support is deprecated, so we hide this interface from users, but +// support for older data. +- (void)readGroup:(int32_t)fieldNumber + message:(GPBMessage *)message + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + +// Reads a group field value from the stream and merges it into the given +// UnknownFieldSet. +- (void)readUnknownGroup:(int32_t)fieldNumber + message:(GPBUnknownFieldSet *)message; + +// Reads a map entry. +- (void)readMapEntry:(id)mapDictionary + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + field:(GPBFieldDescriptor *)field + parentMessage:(GPBMessage *)parentMessage; +@end + +CF_EXTERN_C_BEGIN + +int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state); + +double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state); +float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state); +uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state); +uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state); +int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state); +uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state); +uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state); +int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state); +int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state); +int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state); +BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state); +NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state) + __attribute((ns_returns_retained)); +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) + __attribute((ns_returns_retained)); +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( + GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); + +size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, + size_t byteLimit); +void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, + size_t oldLimit); +size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state); +BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state); +void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, + int32_t value); + +CF_EXTERN_C_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.h new file mode 100644 index 0000000..23c404b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.h @@ -0,0 +1,748 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" +#import "GPBWireFormat.h" + +@class GPBBoolArray; +@class GPBDoubleArray; +@class GPBEnumArray; +@class GPBFloatArray; +@class GPBMessage; +@class GPBInt32Array; +@class GPBInt64Array; +@class GPBUInt32Array; +@class GPBUInt64Array; +@class GPBUnknownFieldSet; + +NS_ASSUME_NONNULL_BEGIN + +/** + * @c GPBCodedOutputStream exception names. + **/ +extern NSString *const GPBCodedOutputStreamException_OutOfSpace; +extern NSString *const GPBCodedOutputStreamException_WriteFailed; + +/** + * Writes out protocol message fields. + * + * The common uses of protocol buffers shouldn't need to use this class. + * GPBMessage's provide a -data method that will serialize the message for you. + * + * @note Any -write* api can raise the GPBCodedOutputStreamException_* + * exceptions. + * + * @note Subclassing of GPBCodedOutputStream is NOT supported. + **/ +@interface GPBCodedOutputStream : NSObject + +/** + * Creates a stream to fill in the given data. Data must be sized to fit or + * an error will be raised when out of space. + * + * @param data The data where the stream will be written to. + * + * @return A newly instanced GPBCodedOutputStream. + **/ ++ (instancetype)streamWithData:(NSMutableData *)data; + +/** + * Creates a stream to write into the given NSOutputStream. + * + * @param output The output stream where the stream will be written to. + * + * @return A newly instanced GPBCodedOutputStream. + **/ ++ (instancetype)streamWithOutputStream:(NSOutputStream *)output; + +/** + * Initializes a stream to fill in the given data. Data must be sized to fit + * or an error will be raised when out of space. + * + * @param data The data where the stream will be written to. + * + * @return A newly initialized GPBCodedOutputStream. + **/ +- (instancetype)initWithData:(NSMutableData *)data; + +/** + * Initializes a stream to write into the given @c NSOutputStream. + * + * @param output The output stream where the stream will be written to. + * + * @return A newly initialized GPBCodedOutputStream. + **/ +- (instancetype)initWithOutputStream:(NSOutputStream *)output; + +/** + * Flush any buffered data out. + **/ +- (void)flush; + +/** + * Write the raw byte out. + * + * @param value The value to write out. + **/ +- (void)writeRawByte:(uint8_t)value; + +/** + * Write the tag for the given field number and wire format. + * + * @param fieldNumber The field number. + * @param format The wire format the data for the field will be in. + **/ +- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format; + +/** + * Write a 32bit value out in little endian format. + * + * @param value The value to write out. + **/ +- (void)writeRawLittleEndian32:(int32_t)value; +/** + * Write a 64bit value out in little endian format. + * + * @param value The value to write out. + **/ +- (void)writeRawLittleEndian64:(int64_t)value; + +/** + * Write a 32bit value out in varint format. + * + * @param value The value to write out. + **/ +- (void)writeRawVarint32:(int32_t)value; +/** + * Write a 64bit value out in varint format. + * + * @param value The value to write out. + **/ +- (void)writeRawVarint64:(int64_t)value; + +/** + * Write a size_t out as a 32bit varint value. + * + * @note This will truncate 64 bit values to 32. + * + * @param value The value to write out. + **/ +- (void)writeRawVarintSizeTAs32:(size_t)value; + +/** + * Writes the contents of an NSData out. + * + * @param data The data to write out. + **/ +- (void)writeRawData:(NSData *)data; +/** + * Writes out the given data. + * + * @param data The data blob to write out. + * @param offset The offset into the blob to start writing out. + * @param length The number of bytes from the blob to write out. + **/ +- (void)writeRawPtr:(const void *)data + offset:(size_t)offset + length:(size_t)length; + +//%PDDM-EXPAND _WRITE_DECLS() +// This block of code is generated, do not edit it directly. + +/** + * Write a double for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeDouble:(int32_t)fieldNumber value:(double)value; +/** + * Write a packed array of double for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag; +/** + * Write a double without any tag. + * + * @param value The value to write out. + **/ +- (void)writeDoubleNoTag:(double)value; + +/** + * Write a float for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeFloat:(int32_t)fieldNumber value:(float)value; +/** + * Write a packed array of float for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag; +/** + * Write a float without any tag. + * + * @param value The value to write out. + **/ +- (void)writeFloatNoTag:(float)value; + +/** + * Write a uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value; +/** + * Write a packed array of uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a uint64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeUInt64NoTag:(uint64_t)value; + +/** + * Write a int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value; +/** + * Write a packed array of int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a int64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeInt64NoTag:(int64_t)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeInt32NoTag:(int32_t)value; + +/** + * Write a uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value; +/** + * Write a packed array of uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a uint32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeUInt32NoTag:(uint32_t)value; + +/** + * Write a uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value; +/** + * Write a packed array of uint64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a uint64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeFixed64NoTag:(uint64_t)value; + +/** + * Write a uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value; +/** + * Write a packed array of uint32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a uint32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeFixed32NoTag:(uint32_t)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSInt32NoTag:(int32_t)value; + +/** + * Write a int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value; +/** + * Write a packed array of int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a int64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSInt64NoTag:(int64_t)value; + +/** + * Write a int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value; +/** + * Write a packed array of int64_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; +/** + * Write a int64_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSFixed64NoTag:(int64_t)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeSFixed32NoTag:(int32_t)value; + +/** + * Write a BOOL for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value; +/** + * Write a packed array of BOOL for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag; +/** + * Write a BOOL without any tag. + * + * @param value The value to write out. + **/ +- (void)writeBoolNoTag:(BOOL)value; + +/** + * Write a int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value; +/** + * Write a packed array of int32_t for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + * @param tag The tag assigned to the values. + **/ +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag; +/** + * Write a int32_t without any tag. + * + * @param value The value to write out. + **/ +- (void)writeEnumNoTag:(int32_t)value; + +/** + * Write a NSString for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeString:(int32_t)fieldNumber value:(NSString *)value; +/** + * Write an array of NSString for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a NSString without any tag. + * + * @param value The value to write out. + **/ +- (void)writeStringNoTag:(NSString *)value; + +/** + * Write a GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value; +/** + * Write an array of GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a GPBMessage without any tag. + * + * @param value The value to write out. + **/ +- (void)writeMessageNoTag:(GPBMessage *)value; + +/** + * Write a NSData for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value; +/** + * Write an array of NSData for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a NSData without any tag. + * + * @param value The value to write out. + **/ +- (void)writeBytesNoTag:(NSData *)value; + +/** + * Write a GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeGroup:(int32_t)fieldNumber + value:(GPBMessage *)value; +/** + * Write an array of GPBMessage for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a GPBMessage without any tag (but does write the endGroup tag). + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeGroupNoTag:(int32_t)fieldNumber + value:(GPBMessage *)value; + +/** + * Write a GPBUnknownFieldSet for the given field number. + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUnknownGroup:(int32_t)fieldNumber + value:(GPBUnknownFieldSet *)value; +/** + * Write an array of GPBUnknownFieldSet for the given field number. + * + * @param fieldNumber The field number assigned to the values. + * @param values The values to write out. + **/ +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values; +/** + * Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag). + * + * @param fieldNumber The field number assigned to the value. + * @param value The value to write out. + **/ +- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber + value:(GPBUnknownFieldSet *)value; + +//%PDDM-EXPAND-END _WRITE_DECLS() + +/** +Write a MessageSet extension field to the stream. For historical reasons, +the wire format differs from normal fields. + +@param fieldNumber The extension field number to write out. +@param value The message from where to get the extension. +*/ +- (void)writeMessageSetExtension:(int32_t)fieldNumber value:(GPBMessage *)value; + +/** +Write an unparsed MessageSet extension field to the stream. For historical +reasons, the wire format differs from normal fields. + +@param fieldNumber The extension field number to write out. +@param value The raw message from where to get the extension. +*/ +- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value; + +@end + +NS_ASSUME_NONNULL_END + +// Write methods for types that can be in packed arrays. +//%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE) +//%/** +//% * Write a TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value; +//%/** +//% * Write a packed array of TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the values. +//% * @param values The values to write out. +//% * @param tag The tag assigned to the values. +//% **/ +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values +//% NAME$S tag:(uint32_t)tag; +//%/** +//% * Write a TYPE without any tag. +//% * +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME##NoTag:(TYPE)value; +//% +// Write methods for types that aren't in packed arrays. +//%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE) +//%/** +//% * Write a TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE *)value; +//%/** +//% * Write an array of TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the values. +//% * @param values The values to write out. +//% **/ +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values; +//%/** +//% * Write a TYPE without any tag. +//% * +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME##NoTag:(TYPE *)value; +//% +// Special write methods for Groups. +//%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE) +//%/** +//% * Write a TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME:(int32_t)fieldNumber +//% NAME$S value:(TYPE *)value; +//%/** +//% * Write an array of TYPE for the given field number. +//% * +//% * @param fieldNumber The field number assigned to the values. +//% * @param values The values to write out. +//% **/ +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values; +//%/** +//% * Write a TYPE without any tag (but does write the endGroup tag). +//% * +//% * @param fieldNumber The field number assigned to the value. +//% * @param value The value to write out. +//% **/ +//%- (void)write##NAME##NoTag:(int32_t)fieldNumber +//% NAME$S value:(TYPE *)value; +//% + +// One macro to hide it all up above. +//%PDDM-DEFINE _WRITE_DECLS() +//%_WRITE_PACKABLE_DECLS(Double, Double, double) +//%_WRITE_PACKABLE_DECLS(Float, Float, float) +//%_WRITE_PACKABLE_DECLS(UInt64, UInt64, uint64_t) +//%_WRITE_PACKABLE_DECLS(Int64, Int64, int64_t) +//%_WRITE_PACKABLE_DECLS(Int32, Int32, int32_t) +//%_WRITE_PACKABLE_DECLS(UInt32, UInt32, uint32_t) +//%_WRITE_PACKABLE_DECLS(Fixed64, UInt64, uint64_t) +//%_WRITE_PACKABLE_DECLS(Fixed32, UInt32, uint32_t) +//%_WRITE_PACKABLE_DECLS(SInt32, Int32, int32_t) +//%_WRITE_PACKABLE_DECLS(SInt64, Int64, int64_t) +//%_WRITE_PACKABLE_DECLS(SFixed64, Int64, int64_t) +//%_WRITE_PACKABLE_DECLS(SFixed32, Int32, int32_t) +//%_WRITE_PACKABLE_DECLS(Bool, Bool, BOOL) +//%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t) +//%_WRITE_UNPACKABLE_DECLS(String, NSString) +//%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage) +//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData) +//%_WRITE_GROUP_DECLS(Group, GPBMessage) +//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.m new file mode 100644 index 0000000..b846c2f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream.m @@ -0,0 +1,1210 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBCodedOutputStream_PackagePrivate.h" + +#import + +#import "GPBArray.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +// These values are the existing values so as not to break any code that might +// have already been inspecting them when they weren't documented/exposed. +NSString *const GPBCodedOutputStreamException_OutOfSpace = @"OutOfSpace"; +NSString *const GPBCodedOutputStreamException_WriteFailed = @"WriteFailed"; + +// Structure for containing state of a GPBCodedInputStream. Brought out into +// a struct so that we can inline several common functions instead of dealing +// with overhead of ObjC dispatch. +typedef struct GPBOutputBufferState { + uint8_t *bytes; + size_t size; + size_t position; + NSOutputStream *output; +} GPBOutputBufferState; + +@implementation GPBCodedOutputStream { + GPBOutputBufferState state_; + NSMutableData *buffer_; +} + +static const int32_t LITTLE_ENDIAN_32_SIZE = sizeof(uint32_t); +static const int32_t LITTLE_ENDIAN_64_SIZE = sizeof(uint64_t); + +// Internal helper that writes the current buffer to the output. The +// buffer position is reset to its initial value when this returns. +static void GPBRefreshBuffer(GPBOutputBufferState *state) { + if (state->output == nil) { + // We're writing to a single buffer. + [NSException raise:GPBCodedOutputStreamException_OutOfSpace format:@""]; + } + if (state->position != 0) { + NSInteger written = + [state->output write:state->bytes maxLength:state->position]; + if (written != (NSInteger)state->position) { + [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""]; + } + state->position = 0; + } +} + +static void GPBWriteRawByte(GPBOutputBufferState *state, uint8_t value) { + if (state->position == state->size) { + GPBRefreshBuffer(state); + } + state->bytes[state->position++] = value; +} + +static void GPBWriteRawVarint32(GPBOutputBufferState *state, int32_t value) { + while (YES) { + if ((value & ~0x7F) == 0) { + uint8_t val = (uint8_t)value; + GPBWriteRawByte(state, val); + return; + } else { + GPBWriteRawByte(state, (value & 0x7F) | 0x80); + value = GPBLogicalRightShift32(value, 7); + } + } +} + +static void GPBWriteRawVarint64(GPBOutputBufferState *state, int64_t value) { + while (YES) { + if ((value & ~0x7FL) == 0) { + uint8_t val = (uint8_t)value; + GPBWriteRawByte(state, val); + return; + } else { + GPBWriteRawByte(state, ((int32_t)value & 0x7F) | 0x80); + value = GPBLogicalRightShift64(value, 7); + } + } +} + +static void GPBWriteInt32NoTag(GPBOutputBufferState *state, int32_t value) { + if (value >= 0) { + GPBWriteRawVarint32(state, value); + } else { + // Must sign-extend + GPBWriteRawVarint64(state, value); + } +} + +static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber, + uint32_t value) { + GPBWriteTagWithFormat(state, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint32(state, value); +} + +static void GPBWriteTagWithFormat(GPBOutputBufferState *state, + uint32_t fieldNumber, GPBWireFormat format) { + GPBWriteRawVarint32(state, GPBWireFormatMakeTag(fieldNumber, format)); +} + +static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state, + int32_t value) { + GPBWriteRawByte(state, (value)&0xFF); + GPBWriteRawByte(state, (value >> 8) & 0xFF); + GPBWriteRawByte(state, (value >> 16) & 0xFF); + GPBWriteRawByte(state, (value >> 24) & 0xFF); +} + +static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, + int64_t value) { + GPBWriteRawByte(state, (int32_t)(value)&0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 8) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 16) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 24) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 32) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 40) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 48) & 0xFF); + GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF); +} + +- (void)dealloc { + [self flush]; + [state_.output close]; + [state_.output release]; + [buffer_ release]; + + [super dealloc]; +} + +- (instancetype)initWithOutputStream:(NSOutputStream *)output { + NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE]; + return [self initWithOutputStream:output data:data]; +} + +- (instancetype)initWithData:(NSMutableData *)data { + return [self initWithOutputStream:nil data:data]; +} + +// This initializer isn't exposed, but it is the designated initializer. +// Setting OutputStream and NSData is to control the buffering behavior/size +// of the work, but that is more obvious via the bufferSize: version. +- (instancetype)initWithOutputStream:(NSOutputStream *)output + data:(NSMutableData *)data { + if ((self = [super init])) { + buffer_ = [data retain]; + state_.bytes = [data mutableBytes]; + state_.size = [data length]; + state_.output = [output retain]; + [state_.output open]; + } + return self; +} + ++ (instancetype)streamWithOutputStream:(NSOutputStream *)output { + NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE]; + return [[[self alloc] initWithOutputStream:output + data:data] autorelease]; +} + ++ (instancetype)streamWithData:(NSMutableData *)data { + return [[[self alloc] initWithData:data] autorelease]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (void)writeDoubleNoTag:(double)value { + GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value)); +} + +- (void)writeDouble:(int32_t)fieldNumber value:(double)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64); + GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value)); +} + +- (void)writeFloatNoTag:(float)value { + GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value)); +} + +- (void)writeFloat:(int32_t)fieldNumber value:(float)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32); + GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value)); +} + +- (void)writeUInt64NoTag:(uint64_t)value { + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeInt64NoTag:(int64_t)value { + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeInt32NoTag:(int32_t)value { + GPBWriteInt32NoTag(&state_, value); +} + +- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteInt32NoTag(&state_, value); +} + +- (void)writeFixed64NoTag:(uint64_t)value { + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64); + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeFixed32NoTag:(uint32_t)value { + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32); + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeBoolNoTag:(BOOL)value { + GPBWriteRawByte(&state_, (value ? 1 : 0)); +} + +- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawByte(&state_, (value ? 1 : 0)); +} + +- (void)writeStringNoTag:(const NSString *)value { + size_t length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + GPBWriteRawVarint32(&state_, (int32_t)length); + if (length == 0) { + return; + } + + const char *quickString = + CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8); + + // Fast path: Most strings are short, if the buffer already has space, + // add to it directly. + NSUInteger bufferBytesLeft = state_.size - state_.position; + if (bufferBytesLeft >= length) { + NSUInteger usedBufferLength = 0; + BOOL result; + if (quickString != NULL) { + memcpy(state_.bytes + state_.position, quickString, length); + usedBufferLength = length; + result = YES; + } else { + result = [value getBytes:state_.bytes + state_.position + maxLength:bufferBytesLeft + usedLength:&usedBufferLength + encoding:NSUTF8StringEncoding + options:(NSStringEncodingConversionOptions)0 + range:NSMakeRange(0, [value length]) + remainingRange:NULL]; + } + if (result) { + NSAssert2((usedBufferLength == length), + @"Our UTF8 calc was wrong? %tu vs %zd", usedBufferLength, + length); + state_.position += usedBufferLength; + return; + } + } else if (quickString != NULL) { + [self writeRawPtr:quickString offset:0 length:length]; + } else { + // Slow path: just get it as data and write it out. + NSData *utf8Data = [value dataUsingEncoding:NSUTF8StringEncoding]; + NSAssert2(([utf8Data length] == length), + @"Strings UTF8 length was wrong? %tu vs %zd", [utf8Data length], + length); + [self writeRawData:utf8Data]; + } +} + +- (void)writeString:(int32_t)fieldNumber value:(NSString *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); + [self writeStringNoTag:value]; +} + +- (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value { + [value writeToCodedOutputStream:self]; + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup); +} + +- (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup); + [self writeGroupNoTag:fieldNumber value:value]; +} + +- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber + value:(const GPBUnknownFieldSet *)value { + [value writeToCodedOutputStream:self]; + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup); +} + +- (void)writeUnknownGroup:(int32_t)fieldNumber + value:(GPBUnknownFieldSet *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup); + [self writeUnknownGroupNoTag:fieldNumber value:value]; +} + +- (void)writeMessageNoTag:(GPBMessage *)value { + GPBWriteRawVarint32(&state_, (int32_t)[value serializedSize]); + [value writeToCodedOutputStream:self]; +} + +- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); + [self writeMessageNoTag:value]; +} + +- (void)writeBytesNoTag:(NSData *)value { + GPBWriteRawVarint32(&state_, (int32_t)[value length]); + [self writeRawData:value]; +} + +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); + [self writeBytesNoTag:value]; +} + +- (void)writeUInt32NoTag:(uint32_t)value { + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value { + GPBWriteUInt32(&state_, fieldNumber, value); +} + +- (void)writeEnumNoTag:(int32_t)value { + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeSFixed32NoTag:(int32_t)value { + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32); + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeSFixed64NoTag:(int64_t)value { + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64); + GPBWriteRawLittleEndian64(&state_, value); +} + +- (void)writeSInt32NoTag:(int32_t)value { + GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value)); +} + +- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value)); +} + +- (void)writeSInt64NoTag:(int64_t)value { + GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value)); +} + +- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value { + GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); + GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value)); +} + +//%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME) +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values +//% NAME$S tag:(uint32_t)tag { +//% if (tag != 0) { +//% if (values.count == 0) return; +//% __block size_t dataSize = 0; +//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { +//%#pragma unused(idx, stop) +//% dataSize += GPBCompute##NAME##SizeNoTag(value); +//% }]; +//% GPBWriteRawVarint32(&state_, tag); +//% GPBWriteRawVarint32(&state_, (int32_t)dataSize); +//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { +//%#pragma unused(idx, stop) +//% [self write##NAME##NoTag:value]; +//% }]; +//% } else { +//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { +//%#pragma unused(idx, stop) +//% [self write##NAME:fieldNumber value:value]; +//% }]; +//% } +//%} +//% +//%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE) +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values { +//% for (TYPE *value in values) { +//% [self write##NAME:fieldNumber value:value]; +//% } +//%} +//% +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, ) +// This block of code is generated, do not edit it directly. + +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeDoubleSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeDoubleNoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeDouble:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, ) +// This block of code is generated, do not edit it directly. + +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeFloatSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFloatNoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFloat:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeUInt64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeInt64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeInt32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeInt32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeUInt32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeUInt32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeFixed64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeFixed32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeFixed32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSInt32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSInt64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSInt64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSFixed64SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed64NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed64:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, ) +// This block of code is generated, do not edit it directly. + +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeSFixed32SizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed32NoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeSFixed32:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, ) +// This block of code is generated, do not edit it directly. + +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeBoolSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeBoolNoTag:value]; + }]; + } else { + [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeBool:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw) +// This block of code is generated, do not edit it directly. + +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag { + if (tag != 0) { + if (values.count == 0) return; + __block size_t dataSize = 0; + [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + dataSize += GPBComputeEnumSizeNoTag(value); + }]; + GPBWriteRawVarint32(&state_, tag); + GPBWriteRawVarint32(&state_, (int32_t)dataSize); + [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeEnumNoTag:value]; + }]; + } else { + [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [self writeEnum:fieldNumber value:value]; + }]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString) +// This block of code is generated, do not edit it directly. + +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values { + for (NSString *value in values) { + [self writeString:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage) +// This block of code is generated, do not edit it directly. + +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values { + for (GPBMessage *value in values) { + [self writeMessage:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData) +// This block of code is generated, do not edit it directly. + +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values { + for (NSData *value in values) { + [self writeBytes:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage) +// This block of code is generated, do not edit it directly. + +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { + for (GPBMessage *value in values) { + [self writeGroup:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet) +// This block of code is generated, do not edit it directly. + +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { + for (GPBUnknownFieldSet *value in values) { + [self writeUnknownGroup:fieldNumber value:value]; + } +} + +//%PDDM-EXPAND-END (19 expansions) + +- (void)writeMessageSetExtension:(int32_t)fieldNumber + value:(GPBMessage *)value { + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatStartGroup); + GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber); + [self writeMessage:GPBWireFormatMessageSetMessage value:value]; + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatEndGroup); +} + +- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value { + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatStartGroup); + GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber); + [self writeBytes:GPBWireFormatMessageSetMessage value:value]; + GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, + GPBWireFormatEndGroup); +} + +- (void)flush { + if (state_.output != nil) { + GPBRefreshBuffer(&state_); + } +} + +- (void)writeRawByte:(uint8_t)value { + GPBWriteRawByte(&state_, value); +} + +- (void)writeRawData:(const NSData *)data { + [self writeRawPtr:[data bytes] offset:0 length:[data length]]; +} + +- (void)writeRawPtr:(const void *)value + offset:(size_t)offset + length:(size_t)length { + if (value == nil || length == 0) { + return; + } + + NSUInteger bufferLength = state_.size; + NSUInteger bufferBytesLeft = bufferLength - state_.position; + if (bufferBytesLeft >= length) { + // We have room in the current buffer. + memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, length); + state_.position += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + size_t bytesWritten = bufferBytesLeft; + memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, + bytesWritten); + offset += bytesWritten; + length -= bytesWritten; + state_.position = bufferLength; + GPBRefreshBuffer(&state_); + bufferLength = state_.size; + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + if (length <= bufferLength) { + // Fits in new buffer. + memcpy(state_.bytes, ((uint8_t *)value) + offset, length); + state_.position = length; + } else { + // Write is very big. Let's do it all at once. + NSInteger written = [state_.output write:((uint8_t *)value) + offset maxLength:length]; + if (written != (NSInteger)length) { + [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""]; + } + } + } +} + +- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format { + GPBWriteTagWithFormat(&state_, fieldNumber, format); +} + +- (void)writeRawVarint32:(int32_t)value { + GPBWriteRawVarint32(&state_, value); +} + +- (void)writeRawVarintSizeTAs32:(size_t)value { + // Note the truncation. + GPBWriteRawVarint32(&state_, (int32_t)value); +} + +- (void)writeRawVarint64:(int64_t)value { + GPBWriteRawVarint64(&state_, value); +} + +- (void)writeRawLittleEndian32:(int32_t)value { + GPBWriteRawLittleEndian32(&state_, value); +} + +- (void)writeRawLittleEndian64:(int64_t)value { + GPBWriteRawLittleEndian64(&state_, value); +} + +#pragma clang diagnostic pop + +@end + +size_t GPBComputeDoubleSizeNoTag(Float64 value) { +#pragma unused(value) + return LITTLE_ENDIAN_64_SIZE; +} + +size_t GPBComputeFloatSizeNoTag(Float32 value) { +#pragma unused(value) + return LITTLE_ENDIAN_32_SIZE; +} + +size_t GPBComputeUInt64SizeNoTag(uint64_t value) { + return GPBComputeRawVarint64Size(value); +} + +size_t GPBComputeInt64SizeNoTag(int64_t value) { + return GPBComputeRawVarint64Size(value); +} + +size_t GPBComputeInt32SizeNoTag(int32_t value) { + if (value >= 0) { + return GPBComputeRawVarint32Size(value); + } else { + // Must sign-extend. + return 10; + } +} + +size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) { + return GPBComputeInt32SizeNoTag((int32_t)value); +} + +size_t GPBComputeFixed64SizeNoTag(uint64_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_64_SIZE; +} + +size_t GPBComputeFixed32SizeNoTag(uint32_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_32_SIZE; +} + +size_t GPBComputeBoolSizeNoTag(BOOL value) { +#pragma unused(value) + return 1; +} + +size_t GPBComputeStringSizeNoTag(NSString *value) { + NSUInteger length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + return GPBComputeRawVarint32SizeForInteger(length) + length; +} + +size_t GPBComputeGroupSizeNoTag(GPBMessage *value) { + return [value serializedSize]; +} + +size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) { + return value.serializedSize; +} + +size_t GPBComputeMessageSizeNoTag(GPBMessage *value) { + size_t size = [value serializedSize]; + return GPBComputeRawVarint32SizeForInteger(size) + size; +} + +size_t GPBComputeBytesSizeNoTag(NSData *value) { + NSUInteger valueLength = [value length]; + return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength; +} + +size_t GPBComputeUInt32SizeNoTag(int32_t value) { + return GPBComputeRawVarint32Size(value); +} + +size_t GPBComputeEnumSizeNoTag(int32_t value) { + return GPBComputeRawVarint32Size(value); +} + +size_t GPBComputeSFixed32SizeNoTag(int32_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_32_SIZE; +} + +size_t GPBComputeSFixed64SizeNoTag(int64_t value) { +#pragma unused(value) + return LITTLE_ENDIAN_64_SIZE; +} + +size_t GPBComputeSInt32SizeNoTag(int32_t value) { + return GPBComputeRawVarint32Size(GPBEncodeZigZag32(value)); +} + +size_t GPBComputeSInt64SizeNoTag(int64_t value) { + return GPBComputeRawVarint64Size(GPBEncodeZigZag64(value)); +} + +size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeDoubleSizeNoTag(value); +} + +size_t GPBComputeFloatSize(int32_t fieldNumber, float value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeFloatSizeNoTag(value); +} + +size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeUInt64SizeNoTag(value); +} + +size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeInt64SizeNoTag(value); +} + +size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeInt32SizeNoTag(value); +} + +size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeFixed64SizeNoTag(value); +} + +size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeFixed32SizeNoTag(value); +} + +size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeBoolSizeNoTag(value); +} + +size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeStringSizeNoTag(value); +} + +size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) { + return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value); +} + +size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, + GPBUnknownFieldSet *value) { + return GPBComputeTagSize(fieldNumber) * 2 + + GPBComputeUnknownGroupSizeNoTag(value); +} + +size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value); +} + +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value); +} + +size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeUInt32SizeNoTag(value); +} + +size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeEnumSizeNoTag(value); +} + +size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed32SizeNoTag(value); +} + +size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed64SizeNoTag(value); +} + +size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeSInt32SizeNoTag(value); +} + +size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) { + return GPBComputeTagSize(fieldNumber) + + GPBComputeRawVarint64Size(GPBEncodeZigZag64(value)); +} + +size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, + GPBMessage *value) { + return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 + + GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) + + GPBComputeMessageSize(GPBWireFormatMessageSetMessage, value); +} + +size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, + NSData *value) { + return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 + + GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) + + GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value); +} + +size_t GPBComputeTagSize(int32_t fieldNumber) { + return GPBComputeRawVarint32Size( + GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint)); +} + +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) { + size_t result = GPBComputeTagSize(field_number); + if (dataType == GPBDataTypeGroup) { + // Groups have both a start and an end tag. + return result * 2; + } else { + return result; + } +} + +size_t GPBComputeRawVarint32Size(int32_t value) { + // value is treated as unsigned, so it won't be sign-extended if negative. + if ((value & (0xffffffff << 7)) == 0) return 1; + if ((value & (0xffffffff << 14)) == 0) return 2; + if ((value & (0xffffffff << 21)) == 0) return 3; + if ((value & (0xffffffff << 28)) == 0) return 4; + return 5; +} + +size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) { + // Note the truncation. + return GPBComputeRawVarint32Size((int32_t)value); +} + +size_t GPBComputeRawVarint64Size(int64_t value) { + if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; + if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; + if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; + if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; + if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; + if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; + if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; + if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; + if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; + return 10; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream_PackagePrivate.h new file mode 100644 index 0000000..2e7bb4c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBCodedOutputStream_PackagePrivate.h @@ -0,0 +1,126 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBCodedOutputStream.h" + +NS_ASSUME_NONNULL_BEGIN + +CF_EXTERN_C_BEGIN + +size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) + __attribute__((const)); +size_t GPBComputeFloatSize(int32_t fieldNumber, float value) + __attribute__((const)); +size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) + __attribute__((const)); +size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) + __attribute__((const)); +size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) + __attribute__((const)); +size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) + __attribute__((const)); +size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) + __attribute__((const)); +size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) + __attribute__((const)); +size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) + __attribute__((const)); +size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) + __attribute__((const)); +size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, + GPBUnknownFieldSet *value) + __attribute__((const)); +size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) + __attribute__((const)); +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) + __attribute__((const)); +size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) + __attribute__((const)); +size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) + __attribute__((const)); +size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) + __attribute__((const)); +size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) + __attribute__((const)); +size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) + __attribute__((const)); +size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const)); +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) + __attribute__((const)); + +size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const)); +size_t GPBComputeFloatSizeNoTag(float value) __attribute__((const)); +size_t GPBComputeUInt64SizeNoTag(uint64_t value) __attribute__((const)); +size_t GPBComputeInt64SizeNoTag(int64_t value) __attribute__((const)); +size_t GPBComputeInt32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeFixed64SizeNoTag(uint64_t value) __attribute__((const)); +size_t GPBComputeFixed32SizeNoTag(uint32_t value) __attribute__((const)); +size_t GPBComputeBoolSizeNoTag(BOOL value) __attribute__((const)); +size_t GPBComputeStringSizeNoTag(NSString *value) __attribute__((const)); +size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const)); +size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) + __attribute__((const)); +size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const)); +size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const)); +size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeEnumSizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeSFixed32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeSFixed64SizeNoTag(int64_t value) __attribute__((const)); +size_t GPBComputeSInt32SizeNoTag(int32_t value) __attribute__((const)); +size_t GPBComputeSInt64SizeNoTag(int64_t value) __attribute__((const)); + +// Note that this will calculate the size of 64 bit values truncated to 32. +size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) __attribute__((const)); + +size_t GPBComputeRawVarint32Size(int32_t value) __attribute__((const)); +size_t GPBComputeRawVarint64Size(int64_t value) __attribute__((const)); + +// Note that this will calculate the size of 64 bit values truncated to 32. +size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) + __attribute__((const)); + +// Compute the number of bytes that would be needed to encode a +// MessageSet extension to the stream. For historical reasons, +// the wire format differs from normal fields. +size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, GPBMessage *value) + __attribute__((const)); + +// Compute the number of bytes that would be needed to encode an +// unparsed MessageSet extension field to the stream. For +// historical reasons, the wire format differs from normal fields. +size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value) + __attribute__((const)); + +size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) + __attribute__((const)); + +CF_EXTERN_C_END + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor.h new file mode 100644 index 0000000..292bce1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor.h @@ -0,0 +1,318 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" + +@class GPBEnumDescriptor; +@class GPBFieldDescriptor; +@class GPBFileDescriptor; +@class GPBOneofDescriptor; + +NS_ASSUME_NONNULL_BEGIN + +/** Syntax used in the proto file. */ +typedef NS_ENUM(uint8_t, GPBFileSyntax) { + /** Unknown syntax. */ + GPBFileSyntaxUnknown = 0, + /** Proto2 syntax. */ + GPBFileSyntaxProto2 = 2, + /** Proto3 syntax. */ + GPBFileSyntaxProto3 = 3, +}; + +/** Type of proto field. */ +typedef NS_ENUM(uint8_t, GPBFieldType) { + /** Optional/required field. Only valid for proto2 fields. */ + GPBFieldTypeSingle, + /** Repeated field. */ + GPBFieldTypeRepeated, + /** Map field. */ + GPBFieldTypeMap, +}; + +/** + * Describes a proto message. + **/ +@interface GPBDescriptor : NSObject + +/** Name of the message. */ +@property(nonatomic, readonly, copy) NSString *name; +/** Fields declared in the message. */ +@property(nonatomic, readonly, strong, nullable) NSArray *fields; +/** Oneofs declared in the message. */ +@property(nonatomic, readonly, strong, nullable) NSArray *oneofs; +/** Extension range declared for the message. */ +@property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges; +/** Number of extension ranges declared for the message. */ +@property(nonatomic, readonly) uint32_t extensionRangesCount; +/** Descriptor for the file where the message was defined. */ +@property(nonatomic, readonly, assign) GPBFileDescriptor *file; + +/** Whether the message is in wire format or not. */ +@property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat; +/** The class of this message. */ +@property(nonatomic, readonly) Class messageClass; +/** Containing message descriptor if this message is nested, or nil otherwise. */ +@property(readonly, nullable) GPBDescriptor *containingType; +/** + * Fully qualified name for this message (package.message). Can be nil if the + * value is unable to be computed. + */ +@property(readonly, nullable) NSString *fullName; + +/** + * Gets the field for the given number. + * + * @param fieldNumber The number for the field to get. + * + * @return The field descriptor for the given number, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; + +/** + * Gets the field for the given name. + * + * @param name The name for the field to get. + * + * @return The field descriptor for the given name, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name; + +/** + * Gets the oneof for the given name. + * + * @param name The name for the oneof to get. + * + * @return The oneof descriptor for the given name, or nil if not found. + **/ +- (nullable GPBOneofDescriptor *)oneofWithName:(NSString *)name; + +@end + +/** + * Describes a proto file. + **/ +@interface GPBFileDescriptor : NSObject + +/** The package declared in the proto file. */ +@property(nonatomic, readonly, copy) NSString *package; +/** The objc prefix declared in the proto file. */ +@property(nonatomic, readonly, copy, nullable) NSString *objcPrefix; +/** The syntax of the proto file. */ +@property(nonatomic, readonly) GPBFileSyntax syntax; + +@end + +/** + * Describes a oneof field. + **/ +@interface GPBOneofDescriptor : NSObject +/** Name of the oneof field. */ +@property(nonatomic, readonly) NSString *name; +/** Fields declared in the oneof. */ +@property(nonatomic, readonly) NSArray *fields; + +/** + * Gets the field for the given number. + * + * @param fieldNumber The number for the field to get. + * + * @return The field descriptor for the given number, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; + +/** + * Gets the field for the given name. + * + * @param name The name for the field to get. + * + * @return The field descriptor for the given name, or nil if not found. + **/ +- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name; + +@end + +/** + * Describes a proto field. + **/ +@interface GPBFieldDescriptor : NSObject + +/** Name of the field. */ +@property(nonatomic, readonly, copy) NSString *name; +/** Number associated with the field. */ +@property(nonatomic, readonly) uint32_t number; +/** Data type contained in the field. */ +@property(nonatomic, readonly) GPBDataType dataType; +/** Whether it has a default value or not. */ +@property(nonatomic, readonly) BOOL hasDefaultValue; +/** Default value for the field. */ +@property(nonatomic, readonly) GPBGenericValue defaultValue; +/** Whether this field is required. Only valid for proto2 fields. */ +@property(nonatomic, readonly, getter=isRequired) BOOL required; +/** Whether this field is optional. */ +@property(nonatomic, readonly, getter=isOptional) BOOL optional; +/** Type of field (single, repeated, map). */ +@property(nonatomic, readonly) GPBFieldType fieldType; +/** Type of the key if the field is a map. The value's type is -fieldType. */ +@property(nonatomic, readonly) GPBDataType mapKeyDataType; +/** Whether the field is packable. */ +@property(nonatomic, readonly, getter=isPackable) BOOL packable; + +/** The containing oneof if this field is part of one, nil otherwise. */ +@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof; + +/** Class of the message if the field is of message type. */ +@property(nonatomic, readonly, assign, nullable) Class msgClass; + +/** Descriptor for the enum if this field is an enum. */ +@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor; + +/** + * Checks whether the given enum raw value is a valid enum value. + * + * @param value The raw enum value to check. + * + * @return YES if value is a valid enum raw value. + **/ +- (BOOL)isValidEnumValue:(int32_t)value; + +/** @return Name for the text format, or nil if not known. */ +- (nullable NSString *)textFormatName; + +@end + +/** + * Describes a proto enum. + **/ +@interface GPBEnumDescriptor : NSObject + +/** Name of the enum. */ +@property(nonatomic, readonly, copy) NSString *name; +/** Function that validates that raw values are valid enum values. */ +@property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier; + +/** + * Returns the enum value name for the given raw enum. + * + * Note that there can be more than one name corresponding to a given value + * if the allow_alias option is used. + * + * @param number The raw enum value. + * + * @return The first name that matches the enum value passed, or nil if not valid. + **/ +- (nullable NSString *)enumNameForValue:(int32_t)number; + +/** + * Gets the enum raw value for the given enum name. + * + * @param outValue A pointer where the value will be set. + * @param name The enum name for which to get the raw value. + * + * @return YES if a value was copied into the pointer, NO otherwise. + **/ +- (BOOL)getValue:(nullable int32_t *)outValue forEnumName:(NSString *)name; + +/** + * Returns the text format for the given raw enum value. + * + * @param number The raw enum value. + * + * @return The first text format name which matches the enum value, or nil if not valid. + **/ +- (nullable NSString *)textFormatNameForValue:(int32_t)number; + +/** + * Gets the enum raw value for the given text format name. + * + * @param outValue A pointer where the value will be set. + * @param textFormatName The text format name for which to get the raw value. + * + * @return YES if a value was copied into the pointer, NO otherwise. + **/ +- (BOOL)getValue:(nullable int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName; + +/** + * Gets the number of defined enum names. + * + * @return Count of the number of enum names, including any aliases. + */ +@property(nonatomic, readonly) uint32_t enumNameCount; + +/** + * Gets the enum name corresponding to the given index. + * + * @param index Index into the available names. The defined range is from 0 + * to self.enumNameCount - 1. + * + * @returns The enum name at the given index, or nil if the index is out of range. + */ +- (nullable NSString *)getEnumNameForIndex:(uint32_t)index; + +/** + * Gets the enum text format name corresponding to the given index. + * + * @param index Index into the available names. The defined range is from 0 + * to self.enumNameCount - 1. + * + * @returns The text format name at the given index, or nil if the index is out of range. + */ +- (nullable NSString *)getEnumTextFormatNameForIndex:(uint32_t)index; + +@end + +/** + * Describes a proto extension. + **/ +@interface GPBExtensionDescriptor : NSObject +/** Field number under which the extension is stored. */ +@property(nonatomic, readonly) uint32_t fieldNumber; +/** The containing message class, i.e. the class extended by this extension. */ +@property(nonatomic, readonly) Class containingMessageClass; +/** Data type contained in the extension. */ +@property(nonatomic, readonly) GPBDataType dataType; +/** Whether the extension is repeated. */ +@property(nonatomic, readonly, getter=isRepeated) BOOL repeated; +/** Whether the extension is packable. */ +@property(nonatomic, readonly, getter=isPackable) BOOL packable; +/** The class of the message if the extension is of message type. */ +@property(nonatomic, readonly, assign) Class msgClass; +/** The singleton name for the extension. */ +@property(nonatomic, readonly) NSString *singletonName; +/** The enum descriptor if the extension is of enum type. */ +@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor; +/** The default value for the extension. */ +@property(nonatomic, readonly, nullable) id defaultValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor.m new file mode 100644 index 0000000..41bf5ad --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor.m @@ -0,0 +1,1123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBDescriptor_PackagePrivate.h" + +#import + +#import "GPBUtilities_PackagePrivate.h" +#import "GPBWireFormat.h" +#import "GPBMessage_PackagePrivate.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +// The addresses of these variables are used as keys for objc_getAssociatedObject. +static const char kTextFormatExtraValueKey = 0; +static const char kParentClassNameValueKey = 0; +static const char kClassNameSuffixKey = 0; + +// Utility function to generate selectors on the fly. +static SEL SelFromStrings(const char *prefix, const char *middle, + const char *suffix, BOOL takesArg) { + if (prefix == NULL && suffix == NULL && !takesArg) { + return sel_getUid(middle); + } + const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; + const size_t middleLen = strlen(middle); + const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; + size_t totalLen = + prefixLen + middleLen + suffixLen + 1; // include space for null on end. + if (takesArg) { + totalLen += 1; + } + char buffer[totalLen]; + if (prefix != NULL) { + memcpy(buffer, prefix, prefixLen); + memcpy(buffer + prefixLen, middle, middleLen); + buffer[prefixLen] = (char)toupper(buffer[prefixLen]); + } else { + memcpy(buffer, middle, middleLen); + } + if (suffix != NULL) { + memcpy(buffer + prefixLen + middleLen, suffix, suffixLen); + } + if (takesArg) { + buffer[totalLen - 2] = ':'; + } + // Always null terminate it. + buffer[totalLen - 1] = 0; + + SEL result = sel_getUid(buffer); + return result; +} + +static NSArray *NewFieldsArrayForHasIndex(int hasIndex, + NSArray *allMessageFields) + __attribute__((ns_returns_retained)); + +static NSArray *NewFieldsArrayForHasIndex(int hasIndex, + NSArray *allMessageFields) { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (GPBFieldDescriptor *fieldDesc in allMessageFields) { + if (fieldDesc->description_->hasIndex == hasIndex) { + [result addObject:fieldDesc]; + } + } + return result; +} + +@implementation GPBDescriptor { + Class messageClass_; + GPBFileDescriptor *file_; + BOOL wireFormat_; +} + +@synthesize messageClass = messageClass_; +@synthesize fields = fields_; +@synthesize oneofs = oneofs_; +@synthesize extensionRanges = extensionRanges_; +@synthesize extensionRangesCount = extensionRangesCount_; +@synthesize file = file_; +@synthesize wireFormat = wireFormat_; + ++ (instancetype) + allocDescriptorForClass:(Class)messageClass + rootClass:(Class)rootClass + file:(GPBFileDescriptor *)file + fields:(void *)fieldDescriptions + fieldCount:(uint32_t)fieldCount + storageSize:(uint32_t)storageSize + flags:(GPBDescriptorInitializationFlags)flags { + // The rootClass is no longer used, but it is passed in to ensure it + // was started up during initialization also. + (void)rootClass; + NSMutableArray *fields = nil; + GPBFileSyntax syntax = file.syntax; + BOOL fieldsIncludeDefault = + (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; + + void *desc; + for (uint32_t i = 0; i < fieldCount; ++i) { + if (fields == nil) { + fields = [[NSMutableArray alloc] initWithCapacity:fieldCount]; + } + // Need correctly typed pointer for array indexing below to work. + if (fieldsIncludeDefault) { + GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions; + desc = &(fieldDescWithDefault[i]); + } else { + GPBMessageFieldDescription *fieldDesc = fieldDescriptions; + desc = &(fieldDesc[i]); + } + GPBFieldDescriptor *fieldDescriptor = + [[GPBFieldDescriptor alloc] initWithFieldDescription:desc + includesDefault:fieldsIncludeDefault + syntax:syntax]; + [fields addObject:fieldDescriptor]; + [fieldDescriptor release]; + } + + BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0; + GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass + file:file + fields:fields + storageSize:storageSize + wireFormat:wireFormat]; + [fields release]; + return descriptor; +} + +- (instancetype)initWithClass:(Class)messageClass + file:(GPBFileDescriptor *)file + fields:(NSArray *)fields + storageSize:(uint32_t)storageSize + wireFormat:(BOOL)wireFormat { + if ((self = [super init])) { + messageClass_ = messageClass; + file_ = file; + fields_ = [fields retain]; + storageSize_ = storageSize; + wireFormat_ = wireFormat; + } + return self; +} + +- (void)dealloc { + [fields_ release]; + [oneofs_ release]; + [super dealloc]; +} + +- (void)setupOneofs:(const char **)oneofNames + count:(uint32_t)count + firstHasIndex:(int32_t)firstHasIndex { + NSCAssert(firstHasIndex < 0, @"Should always be <0"); + NSMutableArray *oneofs = [[NSMutableArray alloc] initWithCapacity:count]; + for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) { + const char *name = oneofNames[i]; + NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_); + NSCAssert(fieldsForOneof.count > 0, + @"No fields for this oneof? (%s:%d)", name, hasIndex); + GPBOneofDescriptor *oneofDescriptor = + [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof]; + [oneofs addObject:oneofDescriptor]; + [oneofDescriptor release]; + [fieldsForOneof release]; + } + oneofs_ = oneofs; +} + +- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo { + // Extra info is a compile time option, so skip the work if not needed. + if (extraTextFormatInfo) { + NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo]; + for (GPBFieldDescriptor *fieldDescriptor in fields_) { + if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) { + objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey, + extraInfoValue, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + } + } +} + +- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count { + extensionRanges_ = ranges; + extensionRangesCount_ = count; +} + +- (void)setupContainingMessageClassName:(const char *)msgClassName { + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). + NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); + NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; + objc_setAssociatedObject(self, &kParentClassNameValueKey, + parentNameValue, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setupMessageClassNameSuffix:(NSString *)suffix { + if (suffix.length) { + objc_setAssociatedObject(self, &kClassNameSuffixKey, + suffix, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } +} + +- (NSString *)name { + return NSStringFromClass(messageClass_); +} + +- (GPBDescriptor *)containingType { + NSValue *parentNameValue = + objc_getAssociatedObject(self, &kParentClassNameValueKey); + if (!parentNameValue) { + return nil; + } + const char *parentName = [parentNameValue pointerValue]; + Class parentClass = objc_getClass(parentName); + NSAssert(parentClass, @"Class %s not defined", parentName); + return [parentClass descriptor]; +} + +- (NSString *)fullName { + NSString *className = NSStringFromClass(self.messageClass); + GPBFileDescriptor *file = self.file; + NSString *objcPrefix = file.objcPrefix; + if (objcPrefix && ![className hasPrefix:objcPrefix]) { + NSAssert(0, + @"Class didn't have correct prefix? (%@ - %@)", + className, objcPrefix); + return nil; + } + GPBDescriptor *parent = self.containingType; + + NSString *name = nil; + if (parent) { + NSString *parentClassName = NSStringFromClass(parent.messageClass); + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); + if (suffix) { + if (![parentClassName hasSuffix:suffix]) { + NSAssert(0, + @"ParentMessage class didn't have correct suffix? (%@ - %@)", + className, suffix); + return nil; + } + parentClassName = + [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; + } + NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; + if (![className hasPrefix:parentPrefix]) { + NSAssert(0, + @"Class didn't have the correct parent name prefix? (%@ - %@)", + parentPrefix, className); + return nil; + } + name = [className substringFromIndex:parentPrefix.length]; + } else { + name = [className substringFromIndex:objcPrefix.length]; + } + + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); + if (suffix) { + if (![name hasSuffix:suffix]) { + NSAssert(0, + @"Message class didn't have correct suffix? (%@ - %@)", + name, suffix); + return nil; + } + name = [name substringToIndex:(name.length - suffix.length)]; + } + + NSString *prefix = (parent != nil ? parent.fullName : file.package); + NSString *result; + if (prefix.length > 0) { + result = [NSString stringWithFormat:@"%@.%@", prefix, name]; + } else { + result = name; + } + return result; +} + +- (id)copyWithZone:(NSZone *)zone { +#pragma unused(zone) + return [self retain]; +} + +- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { + for (GPBFieldDescriptor *descriptor in fields_) { + if (GPBFieldNumber(descriptor) == fieldNumber) { + return descriptor; + } + } + return nil; +} + +- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { + for (GPBFieldDescriptor *descriptor in fields_) { + if ([descriptor.name isEqual:name]) { + return descriptor; + } + } + return nil; +} + +- (GPBOneofDescriptor *)oneofWithName:(NSString *)name { + for (GPBOneofDescriptor *descriptor in oneofs_) { + if ([descriptor.name isEqual:name]) { + return descriptor; + } + } + return nil; +} + +@end + +@implementation GPBFileDescriptor { + NSString *package_; + NSString *objcPrefix_; + GPBFileSyntax syntax_; +} + +@synthesize package = package_; +@synthesize objcPrefix = objcPrefix_; +@synthesize syntax = syntax_; + +- (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax { + self = [super init]; + if (self) { + package_ = [package copy]; + objcPrefix_ = [objcPrefix copy]; + syntax_ = syntax; + } + return self; +} + +- (instancetype)initWithPackage:(NSString *)package + syntax:(GPBFileSyntax)syntax { + self = [super init]; + if (self) { + package_ = [package copy]; + syntax_ = syntax; + } + return self; +} + +- (void)dealloc { + [package_ release]; + [objcPrefix_ release]; + [super dealloc]; +} + +@end + +@implementation GPBOneofDescriptor + +@synthesize fields = fields_; + +- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { + self = [super init]; + if (self) { + name_ = name; + fields_ = [fields retain]; + for (GPBFieldDescriptor *fieldDesc in fields) { + fieldDesc->containingOneof_ = self; + } + + caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO); + } + return self; +} + +- (void)dealloc { + [fields_ release]; + [super dealloc]; +} + +- (NSString *)name { + return (NSString * _Nonnull)@(name_); +} + +- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { + for (GPBFieldDescriptor *descriptor in fields_) { + if (GPBFieldNumber(descriptor) == fieldNumber) { + return descriptor; + } + } + return nil; +} + +- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { + for (GPBFieldDescriptor *descriptor in fields_) { + if ([descriptor.name isEqual:name]) { + return descriptor; + } + } + return nil; +} + +@end + +uint32_t GPBFieldTag(GPBFieldDescriptor *self) { + GPBMessageFieldDescription *description = self->description_; + GPBWireFormat format; + if ((description->flags & GPBFieldMapKeyMask) != 0) { + // Maps are repeated messages on the wire. + format = GPBWireFormatForType(GPBDataTypeMessage, NO); + } else { + format = GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) != 0)); + } + return GPBWireFormatMakeTag(description->number, format); +} + +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { + GPBMessageFieldDescription *description = self->description_; + NSCAssert((description->flags & GPBFieldRepeated) != 0, + @"Only valid on repeated fields"); + GPBWireFormat format = + GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) == 0)); + return GPBWireFormatMakeTag(description->number, format); +} + +@implementation GPBFieldDescriptor { + GPBGenericValue defaultValue_; + + // Message ivars + Class msgClass_; + + // Enum ivars. + // If protos are generated with GenerateEnumDescriptors on then it will + // be a enumDescriptor, otherwise it will be a enumVerifier. + union { + GPBEnumDescriptor *enumDescriptor_; + GPBEnumValidationFunc enumVerifier_; + } enumHandling_; +} + +@synthesize msgClass = msgClass_; +@synthesize containingOneof = containingOneof_; + +- (instancetype)init { + // Throw an exception if people attempt to not use the designated initializer. + self = [super init]; + if (self != nil) { + [self doesNotRecognizeSelector:_cmd]; + self = nil; + } + return self; +} + +- (instancetype)initWithFieldDescription:(void *)description + includesDefault:(BOOL)includesDefault + syntax:(GPBFileSyntax)syntax { + if ((self = [super init])) { + GPBMessageFieldDescription *coreDesc; + if (includesDefault) { + coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core); + } else { + coreDesc = description; + } + description_ = coreDesc; + getSel_ = sel_getUid(coreDesc->name); + setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES); + + GPBDataType dataType = coreDesc->dataType; + BOOL isMessage = GPBDataTypeIsMessage(dataType); + BOOL isMapOrArray = GPBFieldIsMapOrArray(self); + + if (isMapOrArray) { + // map<>/repeated fields get a *Count property (inplace of a has*) to + // support checking if there are any entries without triggering + // autocreation. + hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); + } else { + // If there is a positive hasIndex, then: + // - All fields types for proto2 messages get has* selectors. + // - Only message fields for proto3 messages get has* selectors. + // Note: the positive check is to handle oneOfs, we can't check + // containingOneof_ because it isn't set until after initialization. + if ((coreDesc->hasIndex >= 0) && + (coreDesc->hasIndex != GPBNoHasBit) && + ((syntax != GPBFileSyntaxProto3) || isMessage)) { + hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); + setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); + } + } + + // Extra type specific data. + if (isMessage) { + const char *className = coreDesc->dataTypeSpecific.className; + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). + msgClass_ = objc_getClass(className); + NSAssert(msgClass_, @"Class %s not defined", className); + } else if (dataType == GPBDataTypeEnum) { + if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { + enumHandling_.enumDescriptor_ = + coreDesc->dataTypeSpecific.enumDescFunc(); + } else { + enumHandling_.enumVerifier_ = + coreDesc->dataTypeSpecific.enumVerifier; + } + } + + // Non map<>/repeated fields can have defaults in proto2 syntax. + if (!isMapOrArray && includesDefault) { + defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue; + if (dataType == GPBDataTypeBytes) { + // Data stored as a length prefixed (network byte order) c-string in + // descriptor structure. + const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; + if (bytes) { + uint32_t length; + memcpy(&length, bytes, sizeof(length)); + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } + } + } + return self; +} + +- (void)dealloc { + if (description_->dataType == GPBDataTypeBytes && + !(description_->flags & GPBFieldRepeated)) { + [defaultValue_.valueData release]; + } + [super dealloc]; +} + +- (GPBDataType)dataType { + return description_->dataType; +} + +- (BOOL)hasDefaultValue { + return (description_->flags & GPBFieldHasDefaultValue) != 0; +} + +- (uint32_t)number { + return description_->number; +} + +- (NSString *)name { + return (NSString * _Nonnull)@(description_->name); +} + +- (BOOL)isRequired { + return (description_->flags & GPBFieldRequired) != 0; +} + +- (BOOL)isOptional { + return (description_->flags & GPBFieldOptional) != 0; +} + +- (GPBFieldType)fieldType { + GPBFieldFlags flags = description_->flags; + if ((flags & GPBFieldRepeated) != 0) { + return GPBFieldTypeRepeated; + } else if ((flags & GPBFieldMapKeyMask) != 0) { + return GPBFieldTypeMap; + } else { + return GPBFieldTypeSingle; + } +} + +- (GPBDataType)mapKeyDataType { + switch (description_->flags & GPBFieldMapKeyMask) { + case GPBFieldMapKeyInt32: + return GPBDataTypeInt32; + case GPBFieldMapKeyInt64: + return GPBDataTypeInt64; + case GPBFieldMapKeyUInt32: + return GPBDataTypeUInt32; + case GPBFieldMapKeyUInt64: + return GPBDataTypeUInt64; + case GPBFieldMapKeySInt32: + return GPBDataTypeSInt32; + case GPBFieldMapKeySInt64: + return GPBDataTypeSInt64; + case GPBFieldMapKeyFixed32: + return GPBDataTypeFixed32; + case GPBFieldMapKeyFixed64: + return GPBDataTypeFixed64; + case GPBFieldMapKeySFixed32: + return GPBDataTypeSFixed32; + case GPBFieldMapKeySFixed64: + return GPBDataTypeSFixed64; + case GPBFieldMapKeyBool: + return GPBDataTypeBool; + case GPBFieldMapKeyString: + return GPBDataTypeString; + + default: + NSAssert(0, @"Not a map type"); + return GPBDataTypeInt32; // For lack of anything better. + } +} + +- (BOOL)isPackable { + return (description_->flags & GPBFieldPacked) != 0; +} + +- (BOOL)isValidEnumValue:(int32_t)value { + NSAssert(description_->dataType == GPBDataTypeEnum, + @"Field Must be of type GPBDataTypeEnum"); + if (description_->flags & GPBFieldHasEnumDescriptor) { + return enumHandling_.enumDescriptor_.enumVerifier(value); + } else { + return enumHandling_.enumVerifier_(value); + } +} + +- (GPBEnumDescriptor *)enumDescriptor { + if (description_->flags & GPBFieldHasEnumDescriptor) { + return enumHandling_.enumDescriptor_; + } else { + return nil; + } +} + +- (GPBGenericValue)defaultValue { + // Depends on the fact that defaultValue_ is initialized either to "0/nil" or + // to an actual defaultValue in our initializer. + GPBGenericValue value = defaultValue_; + + if (!(description_->flags & GPBFieldRepeated)) { + // We special handle data and strings. If they are nil, we replace them + // with empty string/empty data. + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes && value.valueData == nil) { + value.valueData = GPBEmptyNSData(); + } else if (type == GPBDataTypeString && value.valueString == nil) { + value.valueString = @""; + } + } + return value; +} + +- (NSString *)textFormatName { + if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) { + NSValue *extraInfoValue = + objc_getAssociatedObject(self, &kTextFormatExtraValueKey); + // Support can be left out at generation time. + if (!extraInfoValue) { + return nil; + } + const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue]; + return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self), + self.name); + } + + // The logic here has to match SetCommonFieldVariables() from + // objectivec_field.cc in the proto compiler. + NSString *name = self.name; + NSUInteger len = [name length]; + + // Remove the "_p" added to reserved names. + if ([name hasSuffix:@"_p"]) { + name = [name substringToIndex:(len - 2)]; + len = [name length]; + } + + // Remove "Array" from the end for repeated fields. + if (((description_->flags & GPBFieldRepeated) != 0) && + [name hasSuffix:@"Array"]) { + name = [name substringToIndex:(len - 5)]; + len = [name length]; + } + + // Groups vs. other fields. + if (description_->dataType == GPBDataTypeGroup) { + // Just capitalize the first letter. + unichar firstChar = [name characterAtIndex:0]; + if (firstChar >= 'a' && firstChar <= 'z') { + NSString *firstCharString = + [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')]; + NSString *result = + [name stringByReplacingCharactersInRange:NSMakeRange(0, 1) + withString:firstCharString]; + return result; + } + return name; + + } else { + // Undo the CamelCase. + NSMutableString *result = [NSMutableString stringWithCapacity:len]; + for (uint32_t i = 0; i < len; i++) { + unichar c = [name characterAtIndex:i]; + if (c >= 'A' && c <= 'Z') { + if (i > 0) { + [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')]; + } else { + [result appendFormat:@"%C", c]; + } + } else { + [result appendFormat:@"%C", c]; + } + } + return result; + } +} + +@end + +@implementation GPBEnumDescriptor { + NSString *name_; + // valueNames_ is a single c string with all of the value names appended + // together, each null terminated. -calcValueNameOffsets fills in + // nameOffsets_ with the offsets to allow quicker access to the individual + // names. + const char *valueNames_; + const int32_t *values_; + GPBEnumValidationFunc enumVerifier_; + const uint8_t *extraTextFormatInfo_; + uint32_t *nameOffsets_; + uint32_t valueCount_; +} + +@synthesize name = name_; +@synthesize enumVerifier = enumVerifier_; + ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier { + GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name + valueNames:valueNames + values:values + count:valueCount + enumVerifier:enumVerifier]; + return descriptor; +} + ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier + extraTextFormatInfo:(const char *)extraTextFormatInfo { + // Call the common case. + GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name + valueNames:valueNames + values:values + count:valueCount + enumVerifier:enumVerifier]; + // Set the extra info. + descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo; + return descriptor; +} + +- (instancetype)initWithName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier { + if ((self = [super init])) { + name_ = [name copy]; + valueNames_ = valueNames; + values_ = values; + valueCount_ = valueCount; + enumVerifier_ = enumVerifier; + } + return self; +} + +- (void)dealloc { + [name_ release]; + if (nameOffsets_) free(nameOffsets_); + [super dealloc]; +} + +- (void)calcValueNameOffsets { + @synchronized(self) { + if (nameOffsets_ != NULL) { + return; + } + uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t)); + if (!offsets) return; + const char *scan = valueNames_; + for (uint32_t i = 0; i < valueCount_; ++i) { + offsets[i] = (uint32_t)(scan - valueNames_); + while (*scan != '\0') ++scan; + ++scan; // Step over the null. + } + nameOffsets_ = offsets; + } +} + +- (NSString *)enumNameForValue:(int32_t)number { + for (uint32_t i = 0; i < valueCount_; ++i) { + if (values_[i] == number) { + return [self getEnumNameForIndex:i]; + } + } + return nil; +} + +- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { + // Must have the prefix. + NSUInteger prefixLen = name_.length + 1; + if ((name.length <= prefixLen) || ![name hasPrefix:name_] || + ([name characterAtIndex:prefixLen - 1] != '_')) { + return NO; + } + + // Skip over the prefix. + const char *nameAsCStr = [name UTF8String]; + nameAsCStr += prefixLen; + + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return NO; + + // Find it. + for (uint32_t i = 0; i < valueCount_; ++i) { + const char *valueName = valueNames_ + nameOffsets_[i]; + if (strcmp(nameAsCStr, valueName) == 0) { + if (outValue) { + *outValue = values_[i]; + } + return YES; + } + } + return NO; +} + +- (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return NO; + + for (uint32_t i = 0; i < valueCount_; ++i) { + NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i]; + if ([valueTextFormatName isEqual:textFormatName]) { + if (outValue) { + *outValue = values_[i]; + } + return YES; + } + } + return NO; +} + +- (NSString *)textFormatNameForValue:(int32_t)number { + // Find the EnumValue descriptor and its index. + BOOL foundIt = NO; + uint32_t valueDescriptorIndex; + for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; + ++valueDescriptorIndex) { + if (values_[valueDescriptorIndex] == number) { + foundIt = YES; + break; + } + } + + if (!foundIt) { + return nil; + } + return [self getEnumTextFormatNameForIndex:valueDescriptorIndex]; +} + +- (uint32_t)enumNameCount { + return valueCount_; +} + +- (NSString *)getEnumNameForIndex:(uint32_t)index { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return nil; + + if (index >= valueCount_) { + return nil; + } + const char *valueName = valueNames_ + nameOffsets_[index]; + NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; + return fullName; +} + +- (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return nil; + + if (index >= valueCount_) { + return nil; + } + NSString *result = nil; + // Naming adds an underscore between enum name and value name, skip that also. + const char *valueName = valueNames_ + nameOffsets_[index]; + NSString *shortName = @(valueName); + + // See if it is in the map of special format handling. + if (extraTextFormatInfo_) { + result = GPBDecodeTextFormatName(extraTextFormatInfo_, + (int32_t)index, shortName); + } + // Logic here needs to match what objectivec_enum.cc does in the proto + // compiler. + if (result == nil) { + NSUInteger len = [shortName length]; + NSMutableString *worker = [NSMutableString stringWithCapacity:len]; + for (NSUInteger i = 0; i < len; i++) { + unichar c = [shortName characterAtIndex:i]; + if (i > 0 && c >= 'A' && c <= 'Z') { + [worker appendString:@"_"]; + } + [worker appendFormat:@"%c", toupper((char)c)]; + } + result = worker; + } + return result; +} + +@end + +@implementation GPBExtensionDescriptor { + GPBGenericValue defaultValue_; +} + +@synthesize containingMessageClass = containingMessageClass_; + +- (instancetype)initWithExtensionDescription: + (GPBExtensionDescription *)description { + if ((self = [super init])) { + description_ = description; + +#if defined(DEBUG) && DEBUG + const char *className = description->messageOrGroupClassName; + if (className) { + NSAssert(objc_lookUpClass(className) != Nil, + @"Class %s not defined", className); + } +#endif + + if (description->extendedClass) { + Class containingClass = objc_lookUpClass(description->extendedClass); + NSAssert(containingClass, @"Class %s not defined", + description->extendedClass); + containingMessageClass_ = containingClass; + } + + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes) { + // Data stored as a length prefixed c-string in descriptor records. + const uint8_t *bytes = + (const uint8_t *)description->defaultValue.valueData; + if (bytes) { + uint32_t length; + memcpy(&length, bytes, sizeof(length)); + // The length is stored in network byte order. + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) { + // The default is looked up in -defaultValue instead since extensions + // aren't common, we avoid the hit startup hit and it avoid initialization + // order issues. + } else { + defaultValue_ = description->defaultValue; + } + } + return self; +} + +- (void)dealloc { + if ((description_->dataType == GPBDataTypeBytes) && + !GPBExtensionIsRepeated(description_)) { + [defaultValue_.valueData release]; + } + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { +#pragma unused(zone) + // Immutable. + return [self retain]; +} + +- (NSString *)singletonName { + return (NSString * _Nonnull)@(description_->singletonName); +} + +- (const char *)singletonNameC { + return description_->singletonName; +} + +- (uint32_t)fieldNumber { + return description_->fieldNumber; +} + +- (GPBDataType)dataType { + return description_->dataType; +} + +- (GPBWireFormat)wireType { + return GPBWireFormatForType(description_->dataType, + GPBExtensionIsPacked(description_)); +} + +- (GPBWireFormat)alternateWireType { + NSAssert(GPBExtensionIsRepeated(description_), + @"Only valid on repeated extensions"); + return GPBWireFormatForType(description_->dataType, + !GPBExtensionIsPacked(description_)); +} + +- (BOOL)isRepeated { + return GPBExtensionIsRepeated(description_); +} + +- (BOOL)isPackable { + return GPBExtensionIsPacked(description_); +} + +- (Class)msgClass { + return objc_getClass(description_->messageOrGroupClassName); +} + +- (GPBEnumDescriptor *)enumDescriptor { + if (description_->dataType == GPBDataTypeEnum) { + GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); + return enumDescriptor; + } + return nil; +} + +- (id)defaultValue { + if (GPBExtensionIsRepeated(description_)) { + return nil; + } + + switch (description_->dataType) { + case GPBDataTypeBool: + return @(defaultValue_.valueBool); + case GPBDataTypeFloat: + return @(defaultValue_.valueFloat); + case GPBDataTypeDouble: + return @(defaultValue_.valueDouble); + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeSFixed32: + return @(defaultValue_.valueInt32); + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeSFixed64: + return @(defaultValue_.valueInt64); + case GPBDataTypeUInt32: + case GPBDataTypeFixed32: + return @(defaultValue_.valueUInt32); + case GPBDataTypeUInt64: + case GPBDataTypeFixed64: + return @(defaultValue_.valueUInt64); + case GPBDataTypeBytes: + // Like message fields, the default is zero length data. + return (defaultValue_.valueData ? defaultValue_.valueData + : GPBEmptyNSData()); + case GPBDataTypeString: + // Like message fields, the default is zero length string. + return (defaultValue_.valueString ? defaultValue_.valueString : @""); + case GPBDataTypeGroup: + case GPBDataTypeMessage: + return nil; + } +} + +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other { + int32_t selfNumber = description_->fieldNumber; + int32_t otherNumber = other->description_->fieldNumber; + if (selfNumber < otherNumber) { + return NSOrderedAscending; + } else if (selfNumber == otherNumber) { + return NSOrderedSame; + } else { + return NSOrderedDescending; + } +} + +@end + +#pragma clang diagnostic pop diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor_PackagePrivate.h new file mode 100644 index 0000000..452b3f8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDescriptor_PackagePrivate.h @@ -0,0 +1,325 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is private to the ProtobolBuffers library and must NOT be +// included by any sources outside this library. The contents of this file are +// subject to change at any time without notice. + +#import "GPBDescriptor.h" +#import "GPBWireFormat.h" + +// Describes attributes of the field. +typedef NS_OPTIONS(uint16_t, GPBFieldFlags) { + GPBFieldNone = 0, + // These map to standard protobuf concepts. + GPBFieldRequired = 1 << 0, + GPBFieldRepeated = 1 << 1, + GPBFieldPacked = 1 << 2, + GPBFieldOptional = 1 << 3, + GPBFieldHasDefaultValue = 1 << 4, + + // Indicates the field needs custom handling for the TextFormat name, if not + // set, the name can be derived from the ObjC name. + GPBFieldTextFormatNameCustom = 1 << 6, + // Indicates the field has an enum descriptor. + GPBFieldHasEnumDescriptor = 1 << 7, + + // These are not standard protobuf concepts, they are specific to the + // Objective C runtime. + + // These bits are used to mark the field as a map and what the key + // type is. + GPBFieldMapKeyMask = 0xF << 8, + GPBFieldMapKeyInt32 = 1 << 8, + GPBFieldMapKeyInt64 = 2 << 8, + GPBFieldMapKeyUInt32 = 3 << 8, + GPBFieldMapKeyUInt64 = 4 << 8, + GPBFieldMapKeySInt32 = 5 << 8, + GPBFieldMapKeySInt64 = 6 << 8, + GPBFieldMapKeyFixed32 = 7 << 8, + GPBFieldMapKeyFixed64 = 8 << 8, + GPBFieldMapKeySFixed32 = 9 << 8, + GPBFieldMapKeySFixed64 = 10 << 8, + GPBFieldMapKeyBool = 11 << 8, + GPBFieldMapKeyString = 12 << 8, +}; + +// NOTE: The structures defined here have their members ordered to minimize +// their size. This directly impacts the size of apps since these exist per +// field/extension. + +// Describes a single field in a protobuf as it is represented as an ivar. +typedef struct GPBMessageFieldDescription { + // Name of ivar. + const char *name; + union { + const char *className; // Name for message class. + // For enums only: If EnumDescriptors are compiled in, it will be that, + // otherwise it will be the verifier. + GPBEnumDescriptorFunc enumDescFunc; + GPBEnumValidationFunc enumVerifier; + } dataTypeSpecific; + // The field number for the ivar. + uint32_t number; + // The index (in bits) into _has_storage_. + // >= 0: the bit to use for a value being set. + // = GPBNoHasBit(INT32_MAX): no storage used. + // < 0: in a oneOf, use a full int32 to record the field active. + int32_t hasIndex; + // Offset of the variable into it's structure struct. + uint32_t offset; + // Field flags. Use accessor functions below. + GPBFieldFlags flags; + // Data type of the ivar. + GPBDataType dataType; +} GPBMessageFieldDescription; + +// Fields in messages defined in a 'proto2' syntax file can provide a default +// value. This struct provides the default along with the field info. +typedef struct GPBMessageFieldDescriptionWithDefault { + // Default value for the ivar. + GPBGenericValue defaultValue; + + GPBMessageFieldDescription core; +} GPBMessageFieldDescriptionWithDefault; + +// Describes attributes of the extension. +typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) { + GPBExtensionNone = 0, + // These map to standard protobuf concepts. + GPBExtensionRepeated = 1 << 0, + GPBExtensionPacked = 1 << 1, + GPBExtensionSetWireFormat = 1 << 2, +}; + +// An extension +typedef struct GPBExtensionDescription { + GPBGenericValue defaultValue; + const char *singletonName; + const char *extendedClass; + const char *messageOrGroupClassName; + GPBEnumDescriptorFunc enumDescriptorFunc; + int32_t fieldNumber; + GPBDataType dataType; + GPBExtensionOptions options; +} GPBExtensionDescription; + +typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { + GPBDescriptorInitializationFlag_None = 0, + GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0, + GPBDescriptorInitializationFlag_WireFormat = 1 << 1, +}; + +@interface GPBDescriptor () { + @package + NSArray *fields_; + NSArray *oneofs_; + uint32_t storageSize_; +} + +// fieldDescriptions have to be long lived, they are held as raw pointers. ++ (instancetype) + allocDescriptorForClass:(Class)messageClass + rootClass:(Class)rootClass + file:(GPBFileDescriptor *)file + fields:(void *)fieldDescriptions + fieldCount:(uint32_t)fieldCount + storageSize:(uint32_t)storageSize + flags:(GPBDescriptorInitializationFlags)flags; + +- (instancetype)initWithClass:(Class)messageClass + file:(GPBFileDescriptor *)file + fields:(NSArray *)fields + storageSize:(uint32_t)storage + wireFormat:(BOOL)wireFormat; + +// Called right after init to provide extra information to avoid init having +// an explosion of args. These pointers are recorded, so they are expected +// to live for the lifetime of the app. +- (void)setupOneofs:(const char **)oneofNames + count:(uint32_t)count + firstHasIndex:(int32_t)firstHasIndex; +- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; +- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; +- (void)setupContainingMessageClassName:(const char *)msgClassName; +- (void)setupMessageClassNameSuffix:(NSString *)suffix; + +@end + +@interface GPBFileDescriptor () +- (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax; +- (instancetype)initWithPackage:(NSString *)package + syntax:(GPBFileSyntax)syntax; +@end + +@interface GPBOneofDescriptor () { + @package + const char *name_; + NSArray *fields_; + SEL caseSel_; +} +// name must be long lived. +- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields; +@end + +@interface GPBFieldDescriptor () { + @package + GPBMessageFieldDescription *description_; + GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_; + + SEL getSel_; + SEL setSel_; + SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise. + SEL setHasSel_; +} + +// Single initializer +// description has to be long lived, it is held as a raw pointer. +- (instancetype)initWithFieldDescription:(void *)description + includesDefault:(BOOL)includesDefault + syntax:(GPBFileSyntax)syntax; +@end + +@interface GPBEnumDescriptor () +// valueNames, values and extraTextFormatInfo have to be long lived, they are +// held as raw pointers. ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier; ++ (instancetype) + allocDescriptorForName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier + extraTextFormatInfo:(const char *)extraTextFormatInfo; + +- (instancetype)initWithName:(NSString *)name + valueNames:(const char *)valueNames + values:(const int32_t *)values + count:(uint32_t)valueCount + enumVerifier:(GPBEnumValidationFunc)enumVerifier; +@end + +@interface GPBExtensionDescriptor () { + @package + GPBExtensionDescription *description_; +} +@property(nonatomic, readonly) GPBWireFormat wireType; + +// For repeated extensions, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the extension was marked packed +// it would be the wire type for unpacked; if the extension was marked unpacked, +// it would be the wire type for packed. +@property(nonatomic, readonly) GPBWireFormat alternateWireType; + +// description has to be long lived, it is held as a raw pointer. +- (instancetype)initWithExtensionDescription: + (GPBExtensionDescription *)description; +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; +@end + +CF_EXTERN_C_BEGIN + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) { + return (field->description_->flags & + (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0; +} + +GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) { + return field->description_->dataType; +} + +GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) { + return field->description_->hasIndex; +} + +GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) { + return field->description_->number; +} + +#pragma clang diagnostic pop + +uint32_t GPBFieldTag(GPBFieldDescriptor *self); + +// For repeated fields, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the field was marked packed it +// would be the wire type for unpacked; if the field was marked unpacked, it +// would be the wire type for packed. +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self); + +GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) { + return syntax == GPBFileSyntaxProto3; +} + +GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) { + return (description->options & GPBExtensionRepeated) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) { + return (description->options & GPBExtensionPacked) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) { + return (description->options & GPBExtensionSetWireFormat) != 0; +} + +// Helper for compile time assets. +#ifndef GPBInternalCompileAssert + #if __has_feature(c_static_assert) || __has_extension(c_static_assert) + #define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg) + #else + // Pre-Xcode 7 support. + #define GPBInternalCompileAssertSymbolInner(line, msg) GPBInternalCompileAssert ## line ## __ ## msg + #define GPBInternalCompileAssertSymbol(line, msg) GPBInternalCompileAssertSymbolInner(line, msg) + #define GPBInternalCompileAssert(test, msg) \ + typedef char GPBInternalCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] + #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert) +#endif // GPBInternalCompileAssert + +// Sanity check that there isn't padding between the field description +// structures with and without a default. +GPBInternalCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) == + (sizeof(GPBGenericValue) + + sizeof(GPBMessageFieldDescription)), + DescriptionsWithDefault_different_size_than_expected); + +CF_EXTERN_C_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary.h new file mode 100644 index 0000000..d00b5b3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary.h @@ -0,0 +1,5770 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRuntimeTypes.h" + +// Note on naming: for the classes holding numeric values, a more natural +// naming of the method might be things like "-valueForKey:", +// "-setValue:forKey:"; etc. But those selectors are also defined by Key Value +// Coding (KVC) as categories on NSObject. So "overloading" the selectors with +// other meanings can cause warnings (based on compiler settings), but more +// importantly, some of those selector get called as KVC breaks up keypaths. +// So if those selectors are used, using KVC will compile cleanly, but could +// crash as it invokes those selectors with the wrong types of arguments. + +NS_ASSUME_NONNULL_BEGIN + +//%PDDM-EXPAND DECLARE_DICTIONARIES() +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt32 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(uint32_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt32 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt32ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(uint32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(uint32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(uint32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(int32_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int32 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt32ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const int32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(int32_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(int32_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(int32_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(uint64_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - UInt64 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBUInt64ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const uint64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(uint64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(uint64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(uint64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64UInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64Int32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64UInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64FloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64DoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64EnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(int64_t)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Int64 -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBInt64ObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const int64_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(int64_t)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(int64_t)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(int64_t)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolUInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolUInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolBoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolFloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolDoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolEnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(BOOL)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - Bool -> Object + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBBoolObjectDictionary<__covariant ObjectType> : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const BOOL [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Fetches the object stored under the given key. + * + * @param key Key under which the value is stored, if present. + * + * @return The object if found, nil otherwise. + **/ +- (ObjectType)objectForKey:(BOOL)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **object**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, ObjectType object, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param object The value to set. + * @param key The key under which to store the value. + **/ +- (void)setObject:(ObjectType)object forKey:(BOOL)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeObjectForKey:(BOOL)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> UInt32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringUInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt32s:(const uint32_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt32:(uint32_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt32ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Int32 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt32s:(const int32_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt32:(nullable int32_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt32:(int32_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt32ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> UInt64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringUInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithUInt64s:(const uint64_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setUInt64:(uint64_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeUInt64ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Int64 + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithInt64s:(const int64_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getInt64:(nullable int64_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int64_t value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setInt64:(int64_t)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeInt64ForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Bool + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringBoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithBools:(const BOOL [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getBool:(nullable BOOL *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, BOOL value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setBool:(BOOL)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeBoolForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Float + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringFloatDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithFloats:(const float [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getFloat:(nullable float *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, float value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setFloat:(float)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeFloatForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Double + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringDoubleDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; + +/** + * Initializes this dictionary, copying the given values and keys. + * + * @param values The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. + * + * @return A newly initialized dictionary with a copy of the values and keys. + **/ +- (instancetype)initWithDoubles:(const double [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes this dictionary, copying the entries from the given dictionary. + * + * @param dictionary Dictionary containing the entries to add to this dictionary. + * + * @return A newly initialized dictionary with the entries of the given dictionary. + **/ +- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary; + +/** + * Initializes this dictionary with the requested capacity. + * + * @param numItems Number of items needed for this dictionary. + * + * @return A newly initialized dictionary with the requested capacity. + **/ +- (instancetype)initWithCapacity:(NSUInteger)numItems; + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getDouble:(nullable double *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, double value, BOOL *stop))block; + +/** + * Adds the keys and values from another dictionary. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary; + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setDouble:(double)value forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeDoubleForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +#pragma mark - String -> Enum + +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. + * + * @note This class is not meant to be subclassed. + **/ +@interface GPBStringEnumDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; +/** The validation function to check if the enums are valid. */ +@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + +/** + * Initializes a dictionary with the given validation function. + * + * @param func The enum validation function for the dictionary. + * + * @return A newly initialized dictionary. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; + +/** + * Initializes a dictionary with the entries given. + * + * @param func The enum validation function for the dictionary. + * @param values The raw enum values values to be placed in the dictionary. + * @param keys The keys under which to store the values. + * @param count The number of entries to store in the dictionary. + * + * @return A newly initialized dictionary with the keys and values in it. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + rawValues:(const int32_t [__nullable])values + forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a dictionary with the entries from the given. + * dictionary. + * + * @param dictionary Dictionary containing the entries to add to the dictionary. + * + * @return A newly initialized dictionary with the entries from the given + * dictionary in it. + **/ +- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary; + +/** + * Initializes a dictionary with the given capacity. + * + * @param func The enum validation function for the dictionary. + * @param numItems Capacity needed for the dictionary. + * + * @return A newly initialized dictionary with the given capacity. + **/ +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems; + +// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +// is not a valid enumerator as defined by validationFunc. If the actual value is +// desired, use "raw" version of the method. + +/** + * Gets the value for the given key. + * + * @param value Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getEnum:(nullable int32_t *)value forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **value**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block; + +/** + * Gets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param rawValue Pointer into which the value will be set, if found. + * @param key Key under which the value is stored, if present. + * + * @return YES if the key was found and the value was copied, NO otherwise. + **/ +- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(NSString *)key; + +/** + * Enumerates the keys and values on this dictionary with the given block. + * + * @note This method bypass the validationFunc to enable the access of values that + * were not known at the time the binary was compiled. + * + * @param block The block to enumerate with. + * **key**: The key for the current entry. + * **rawValue**: The value for the current entry + * **stop**: A pointer to a boolean that when set stops the enumeration. + **/ +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t rawValue, BOOL *stop))block; + +/** + * Adds the keys and raw enum values from another dictionary. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param otherDictionary Dictionary containing entries to be added to this + * dictionary. + **/ +- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary; + +// If value is not a valid enumerator as defined by validationFunc, these +// methods will assert in debug, and will log in release and assign the value +// to the default value. Use the rawValue methods below to assign non enumerator +// values. + +/** + * Sets the value for the given key. + * + * @param value The value to set. + * @param key The key under which to store the value. + **/ +- (void)setEnum:(int32_t)value forKey:(NSString *)key; + +/** + * Sets the raw enum value for the given key. + * + * @note This method bypass the validationFunc to enable the setting of values that + * were not known at the time the binary was compiled. + * + * @param rawValue The raw enum value to set. + * @param key The key under which to store the raw enum value. + **/ +- (void)setRawValue:(int32_t)rawValue forKey:(NSString *)key; + +/** + * Removes the entry for the given key. + * + * @param aKey Key to be removed from this dictionary. + **/ +- (void)removeEnumForKey:(NSString *)aKey; + +/** + * Removes all entries in this dictionary. + **/ +- (void)removeAll; + +@end + +//%PDDM-EXPAND-END DECLARE_DICTIONARIES() + +NS_ASSUME_NONNULL_END + +//%PDDM-DEFINE DECLARE_DICTIONARIES() +//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt32, uint32_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int32, int32_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt64, uint64_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int64, int64_t) +//%DICTIONARY_INTERFACES_FOR_POD_KEY(Bool, BOOL) +//%DICTIONARY_POD_INTERFACES_FOR_KEY(String, NSString, *, OBJECT) +//%PDDM-DEFINE DICTIONARY_INTERFACES_FOR_POD_KEY(KEY_NAME, KEY_TYPE) +//%DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, , POD) +//%DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, Object, ObjectType) +//%PDDM-DEFINE DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt32, uint32_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int32, int32_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt64, uint64_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int64, int64_t) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Bool, BOOL) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Float, float) +//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Double, double) +//%DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Enum, int32_t) +//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, POD, VALUE_NAME, value) +//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, , POD, VALUE_NAME, VALUE_TYPE, OBJECT, Object, object) +//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE, VNAME) +//%/** +//% * Gets the value for the given key. +//% * +//% * @param value Pointer into which the value will be set, if found. +//% * @param key Key under which the value is stored, if present. +//% * +//% * @return YES if the key was found and the value was copied, NO otherwise. +//% **/ +//%- (BOOL)get##VNAME##:(nullable VALUE_TYPE *)value forKey:(KEY_TYPE)key; +//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_TYPE, VNAME) +//%/** +//% * Fetches the object stored under the given key. +//% * +//% * @param key Key under which the value is stored, if present. +//% * +//% * @return The object if found, nil otherwise. +//% **/ +//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key; +//%PDDM-DEFINE VALUE_FOR_KEY_Enum(KEY_TYPE, VALUE_TYPE, VNAME) +//%VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE, VNAME) +//%PDDM-DEFINE ARRAY_ARG_MODIFIERPOD() +// Nothing +//%PDDM-DEFINE ARRAY_ARG_MODIFIEREnum() +// Nothing +//%PDDM-DEFINE ARRAY_ARG_MODIFIEROBJECT() +//%__nonnull GPB_UNSAFE_UNRETAINED ## +//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE) +//%GPB##KEY_NAME##VALUE_NAME##Dictionary +//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE) +//%GPB##KEY_NAME##VALUE_NAME##Dictionary +//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE) +//%GPB##KEY_NAME##VALUE_NAME##Dictionary<__covariant VALUE_TYPE> +//%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%/** +//% * Class used for map fields of <##KEY_TYPE##, ##VALUE_TYPE##> +//% * values. This performs better than boxing into NSNumbers in NSDictionaries. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) : NSObject +//% +//%/** Number of entries stored in this dictionary. */ +//%@property(nonatomic, readonly) NSUInteger count; +//% +//%/** +//% * Initializes this dictionary, copying the given values and keys. +//% * +//% * @param ##VNAME_VAR##s The values to be placed in this dictionary. +//% * @param keys ##VNAME_VAR$S## The keys under which to store the values. +//% * @param count ##VNAME_VAR$S## The number of elements to copy into the dictionary. +//% * +//% * @return A newly initialized dictionary with a copy of the values and keys. +//% **/ +//%- (instancetype)initWith##VNAME##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[__nullable])##VNAME_VAR##s +//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[__nullable])keys +//% ##VNAME$S## count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes this dictionary, copying the entries from the given dictionary. +//% * +//% * @param dictionary Dictionary containing the entries to add to this dictionary. +//% * +//% * @return A newly initialized dictionary with the entries of the given dictionary. +//% **/ +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary; +//% +//%/** +//% * Initializes this dictionary with the requested capacity. +//% * +//% * @param numItems Number of items needed for this dictionary. +//% * +//% * @return A newly initialized dictionary with the requested capacity. +//% **/ +//%- (instancetype)initWithCapacity:(NSUInteger)numItems; +//% +//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//% +//%/** +//% * Adds the keys and values from another dictionary. +//% * +//% * @param otherDictionary Dictionary containing entries to be added to this +//% * dictionary. +//% **/ +//%- (void)addEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary; +//% +//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, Enum) +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%/** +//% * Class used for map fields of <##KEY_TYPE##, ##VALUE_TYPE##> +//% * values. This performs better than boxing into NSNumbers in NSDictionaries. +//% * +//% * @note This class is not meant to be subclassed. +//% **/ +//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject +//% +//%/** Number of entries stored in this dictionary. */ +//%@property(nonatomic, readonly) NSUInteger count; +//%/** The validation function to check if the enums are valid. */ +//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; +//% +//%/** +//% * Initializes a dictionary with the given validation function. +//% * +//% * @param func The enum validation function for the dictionary. +//% * +//% * @return A newly initialized dictionary. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//% +//%/** +//% * Initializes a dictionary with the entries given. +//% * +//% * @param func The enum validation function for the dictionary. +//% * @param values The raw enum values values to be placed in the dictionary. +//% * @param keys The keys under which to store the values. +//% * @param count The number of entries to store in the dictionary. +//% * +//% * @return A newly initialized dictionary with the keys and values in it. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[__nullable])values +//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[__nullable])keys +//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; +//% +//%/** +//% * Initializes a dictionary with the entries from the given. +//% * dictionary. +//% * +//% * @param dictionary Dictionary containing the entries to add to the dictionary. +//% * +//% * @return A newly initialized dictionary with the entries from the given +//% * dictionary in it. +//% **/ +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary; +//% +//%/** +//% * Initializes a dictionary with the given capacity. +//% * +//% * @param func The enum validation function for the dictionary. +//% * @param numItems Capacity needed for the dictionary. +//% * +//% * @return A newly initialized dictionary with the given capacity. +//% **/ +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func +//% capacity:(NSUInteger)numItems; +//% +//%// These will return kGPBUnrecognizedEnumeratorValue if the value for the key +//%// is not a valid enumerator as defined by validationFunc. If the actual value is +//%// desired, use "raw" version of the method. +//% +//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, Enum, value) +//% +//%/** +//% * Gets the raw enum value for the given key. +//% * +//% * @note This method bypass the validationFunc to enable the access of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param rawValue Pointer into which the value will be set, if found. +//% * @param key Key under which the value is stored, if present. +//% * +//% * @return YES if the key was found and the value was copied, NO otherwise. +//% **/ +//%- (BOOL)getRawValue:(nullable VALUE_TYPE *)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key; +//% +//%/** +//% * Enumerates the keys and values on this dictionary with the given block. +//% * +//% * @note This method bypass the validationFunc to enable the access of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param block The block to enumerate with. +//% * **key**: The key for the current entry. +//% * **rawValue**: The value for the current entry +//% * **stop**: A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateKeysAndRawValuesUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block; +//% +//%/** +//% * Adds the keys and raw enum values from another dictionary. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param otherDictionary Dictionary containing entries to be added to this +//% * dictionary. +//% **/ +//%- (void)addRawEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary; +//% +//%// If value is not a valid enumerator as defined by validationFunc, these +//%// methods will assert in debug, and will log in release and assign the value +//%// to the default value. Use the rawValue methods below to assign non enumerator +//%// values. +//% +//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, Enum, value) +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_TYPE, VNAME) +//% +//%/** +//% * Enumerates the keys and values on this dictionary with the given block. +//% * +//% * @param block The block to enumerate with. +//% * **key**: ##VNAME_VAR$S## The key for the current entry. +//% * **VNAME_VAR**: The value for the current entry +//% * **stop**: ##VNAME_VAR$S## A pointer to a boolean that when set stops the enumeration. +//% **/ +//%- (void)enumerateKeysAnd##VNAME##sUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block; + +//%PDDM-DEFINE DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) +//%/** +//% * Sets the value for the given key. +//% * +//% * @param ##VNAME_VAR The value to set. +//% * @param key ##VNAME_VAR$S## The key under which to store the value. +//% **/ +//%- (void)set##VNAME##:(VALUE_TYPE)##VNAME_VAR forKey:(KEY_TYPE##KisP$S##KisP)key; +//%DICTIONARY_EXTRA_MUTABLE_METHODS_##VHELPER(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +//%/** +//% * Removes the entry for the given key. +//% * +//% * @param aKey Key to be removed from this dictionary. +//% **/ +//%- (void)remove##VNAME##ForKey:(KEY_TYPE##KisP$S##KisP)aKey; +//% +//%/** +//% * Removes all entries in this dictionary. +//% **/ +//%- (void)removeAll; + +//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_POD(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +// Empty +//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_OBJECT(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +// Empty +//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_Enum(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE) +//% +//%/** +//% * Sets the raw enum value for the given key. +//% * +//% * @note This method bypass the validationFunc to enable the setting of values that +//% * were not known at the time the binary was compiled. +//% * +//% * @param rawValue The raw enum value to set. +//% * @param key The key under which to store the raw enum value. +//% **/ +//%- (void)setRawValue:(VALUE_TYPE)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key; +//% diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary.m new file mode 100644 index 0000000..1bb24be --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary.m @@ -0,0 +1,12120 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBDictionary_PackagePrivate.h" + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +// ------------------------------ NOTE ------------------------------ +// At the moment, this is all using NSNumbers in NSDictionaries under +// the hood, but it is all hidden so we can come back and optimize +// with direct CFDictionary usage later. The reason that wasn't +// done yet is needing to support 32bit iOS builds. Otherwise +// it would be pretty simple to store all this data in CFDictionaries +// directly. +// ------------------------------------------------------------------ + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +// Used to include code only visible to specific versions of the static +// analyzer. Useful for wrapping code that only exists to silence the analyzer. +// Determine the values you want to use for BEGIN_APPLE_BUILD_VERSION, +// END_APPLE_BUILD_VERSION using: +// xcrun clang -dM -E -x c /dev/null | grep __apple_build_version__ +// Example usage: +// #if GPB_STATIC_ANALYZER_ONLY(5621, 5623) ... #endif +#define GPB_STATIC_ANALYZER_ONLY(BEGIN_APPLE_BUILD_VERSION, END_APPLE_BUILD_VERSION) \ + (defined(__clang_analyzer__) && \ + (__apple_build_version__ >= BEGIN_APPLE_BUILD_VERSION && \ + __apple_build_version__ <= END_APPLE_BUILD_VERSION)) + +enum { + kMapKeyFieldNumber = 1, + kMapValueFieldNumber = 2, +}; + +static BOOL DictDefault_IsValidValue(int32_t value) { + // Anything but the bad value marker is allowed. + return (value != kGPBUnrecognizedEnumeratorValue); +} + +//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% return 0; +//% } +//%} +//% +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% } +//%} +//% +//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2, GPBDATATYPE_NAME3) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% return GPBCompute##GPBDATATYPE_NAME3##Size(fieldNum, value); +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% return 0; +//% } +//%} +//% +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% [stream write##GPBDATATYPE_NAME3##:fieldNum value:value]; +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", dataType); +//% } +//%} +//% +//%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. +//% return GPBCompute##VALUE_NAME##Size(fieldNum, value); +//%} +//% +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. +//% [stream write##VALUE_NAME##:fieldNum value:value]; +//%} +//% +//%PDDM-DEFINE SERIALIZE_SUPPORT_HELPERS() +//%SERIALIZE_SUPPORT_3_TYPE(Int32, int32_t, Int32, SInt32, SFixed32) +//%SERIALIZE_SUPPORT_2_TYPE(UInt32, uint32_t, UInt32, Fixed32) +//%SERIALIZE_SUPPORT_3_TYPE(Int64, int64_t, Int64, SInt64, SFixed64) +//%SERIALIZE_SUPPORT_2_TYPE(UInt64, uint64_t, UInt64, Fixed64) +//%SIMPLE_SERIALIZE_SUPPORT(Bool, BOOL, ) +//%SIMPLE_SERIALIZE_SUPPORT(Enum, int32_t, ) +//%SIMPLE_SERIALIZE_SUPPORT(Float, float, ) +//%SIMPLE_SERIALIZE_SUPPORT(Double, double, ) +//%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *) +//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes) +//%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS() +// This block of code is generated, do not edit it directly. + +static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { + return GPBComputeInt32Size(fieldNum, value); + } else if (dataType == GPBDataTypeSInt32) { + return GPBComputeSInt32Size(fieldNum, value); + } else if (dataType == GPBDataTypeSFixed32) { + return GPBComputeSFixed32Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { + [stream writeInt32:fieldNum value:value]; + } else if (dataType == GPBDataTypeSInt32) { + [stream writeSInt32:fieldNum value:value]; + } else if (dataType == GPBDataTypeSFixed32) { + [stream writeSFixed32:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { + return GPBComputeUInt32Size(fieldNum, value); + } else if (dataType == GPBDataTypeFixed32) { + return GPBComputeFixed32Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { + [stream writeUInt32:fieldNum value:value]; + } else if (dataType == GPBDataTypeFixed32) { + [stream writeFixed32:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { + return GPBComputeInt64Size(fieldNum, value); + } else if (dataType == GPBDataTypeSInt64) { + return GPBComputeSInt64Size(fieldNum, value); + } else if (dataType == GPBDataTypeSFixed64) { + return GPBComputeSFixed64Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { + [stream writeInt64:fieldNum value:value]; + } else if (dataType == GPBDataTypeSInt64) { + [stream writeSInt64:fieldNum value:value]; + } else if (dataType == GPBDataTypeSFixed64) { + [stream writeSFixed64:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { + return GPBComputeUInt64Size(fieldNum, value); + } else if (dataType == GPBDataTypeFixed64) { + return GPBComputeFixed64Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { + [stream writeUInt64:fieldNum value:value]; + } else if (dataType == GPBDataTypeFixed64) { + [stream writeFixed64:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeBoolSize(fieldNum, value); +} + +static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeBool:fieldNum value:value]; +} + +static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeEnumSize(fieldNum, value); +} + +static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeEnum:fieldNum value:value]; +} + +static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeFloatSize(fieldNum, value); +} + +static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeFloat:fieldNum value:value]; +} + +static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeDoubleSize(fieldNum, value); +} + +static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeDouble:fieldNum value:value]; +} + +static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + return GPBComputeStringSize(fieldNum, value); +} + +static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. + [stream writeString:fieldNum value:value]; +} + +static size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { + return GPBComputeMessageSize(fieldNum, value); + } else if (dataType == GPBDataTypeString) { + return GPBComputeStringSize(fieldNum, value); + } else if (dataType == GPBDataTypeBytes) { + return GPBComputeBytesSize(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + return 0; + } +} + +static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { + [stream writeMessage:fieldNum value:value]; + } else if (dataType == GPBDataTypeString) { + [stream writeString:fieldNum value:value]; + } else if (dataType == GPBDataTypeBytes) { + [stream writeBytes:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", dataType); + } +} + +//%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS() + +size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { + GPBDataType mapValueType = GPBGetFieldDataType(field); + size_t result = 0; + NSString *key; + NSEnumerator *keys = [dict keyEnumerator]; + while ((key = [keys nextObject])) { + id obj = dict[key]; + size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key); + msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * dict.count; + return result; +} + +void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream, + NSDictionary *dict, + GPBFieldDescriptor *field) { + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + GPBDataType mapValueType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSString *key; + NSEnumerator *keys = [dict keyEnumerator]; + while ((key = [keys nextObject])) { + id obj = dict[key]; + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key); + msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType); + + // Write the size and fields. + [outputStream writeInt32NoTag:(int32_t)msgSize]; + [outputStream writeString:kMapKeyFieldNumber value:key]; + WriteDictObjectField(outputStream, obj, kMapValueFieldNumber, mapValueType); + } +} + +BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type"); + #pragma unused(field) // For when asserts are off in release. + GPBMessage *msg; + NSEnumerator *objects = [dict objectEnumerator]; + while ((msg = [objects nextObject])) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +// Note: if the type is an object, it the retain pass back to the caller. +static void ReadValue(GPBCodedInputStream *stream, + GPBGenericValue *valueToFill, + GPBDataType type, + GPBExtensionRegistry *registry, + GPBFieldDescriptor *field) { + switch (type) { + case GPBDataTypeBool: + valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_); + break; + case GPBDataTypeFixed32: + valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_); + break; + case GPBDataTypeSFixed32: + valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_); + break; + case GPBDataTypeFloat: + valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_); + break; + case GPBDataTypeFixed64: + valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_); + break; + case GPBDataTypeSFixed64: + valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_); + break; + case GPBDataTypeDouble: + valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_); + break; + case GPBDataTypeInt32: + valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_); + break; + case GPBDataTypeInt64: + valueToFill->valueInt64 = GPBCodedInputStreamReadInt64(&stream->state_); + break; + case GPBDataTypeSInt32: + valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_); + break; + case GPBDataTypeSInt64: + valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_); + break; + case GPBDataTypeUInt32: + valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_); + break; + case GPBDataTypeUInt64: + valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_); + break; + case GPBDataTypeBytes: + [valueToFill->valueData release]; + valueToFill->valueData = GPBCodedInputStreamReadRetainedBytes(&stream->state_); + break; + case GPBDataTypeString: + [valueToFill->valueString release]; + valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_); + break; + case GPBDataTypeMessage: { + GPBMessage *message = [[field.msgClass alloc] init]; + [stream readMessage:message extensionRegistry:registry]; + [valueToFill->valueMessage release]; + valueToFill->valueMessage = message; + break; + } + case GPBDataTypeGroup: + NSCAssert(NO, @"Can't happen"); + break; + case GPBDataTypeEnum: + valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_); + break; + } +} + +void GPBDictionaryReadEntry(id mapDictionary, + GPBCodedInputStream *stream, + GPBExtensionRegistry *registry, + GPBFieldDescriptor *field, + GPBMessage *parentMessage) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + + GPBGenericValue key; + GPBGenericValue value; + // Zero them (but pick up any enum default for proto2). + key.valueString = value.valueString = nil; + if (valueDataType == GPBDataTypeEnum) { + value = field.defaultValue; + } + + GPBCodedInputStreamState *state = &stream->state_; + uint32_t keyTag = + GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO)); + uint32_t valueTag = + GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO)); + + BOOL hitError = NO; + while (YES) { + uint32_t tag = GPBCodedInputStreamReadTag(state); + if (tag == keyTag) { + ReadValue(stream, &key, keyDataType, registry, field); + } else if (tag == valueTag) { + ReadValue(stream, &value, valueDataType, registry, field); + } else if (tag == 0) { + // zero signals EOF / limit reached + break; + } else { // Unknown + if (![stream skipField:tag]){ + hitError = YES; + break; + } + } + } + + if (!hitError) { + // Handle the special defaults and/or missing key/value. + if ((keyDataType == GPBDataTypeString) && (key.valueString == nil)) { + key.valueString = [@"" retain]; + } + if (GPBDataTypeIsObject(valueDataType) && value.valueString == nil) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (valueDataType) { + case GPBDataTypeString: + value.valueString = [@"" retain]; + break; + case GPBDataTypeBytes: + value.valueData = [GPBEmptyNSData() retain]; + break; +#if defined(__clang_analyzer__) + case GPBDataTypeGroup: + // Maps can't really have Groups as the value type, but this case is needed + // so the analyzer won't report the posibility of send nil in for the value + // in the NSMutableDictionary case below. +#endif + case GPBDataTypeMessage: { + value.valueMessage = [[field.msgClass alloc] init]; + break; + } + default: + // Nothing + break; + } +#pragma clang diagnostic pop + } + + if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) { +#if GPB_STATIC_ANALYZER_ONLY(6020053, 7000181) + // Limited to Xcode 6.4 - 7.2, are known to fail here. The upper end can + // be raised as needed for new Xcodes. + // + // This is only needed on a "shallow" analyze; on a "deep" analyze, the + // existing code path gets this correct. In shallow, the analyzer decides + // GPBDataTypeIsObject(valueDataType) is both false and true on a single + // path through this function, allowing nil to be used for the + // setObject:forKey:. + if (value.valueString == nil) { + value.valueString = [@"" retain]; + } +#endif + // mapDictionary is an NSMutableDictionary + [(NSMutableDictionary *)mapDictionary setObject:value.valueString + forKey:key.valueString]; + } else { + if (valueDataType == GPBDataTypeEnum) { + if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) || + [field isValidEnumValue:value.valueEnum]) { + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; + } else { + NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum + forKey:&key + keyDataType:keyDataType]; + [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data]; + } + } else { + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; + } + } + } + + if (GPBDataTypeIsObject(keyDataType)) { + [key.valueString release]; + } + if (GPBDataTypeIsObject(valueDataType)) { + [value.valueString release]; + } +} + +// +// Macros for the common basic cases. +// + +//%PDDM-DEFINE DICTIONARY_IMPL_FOR_POD_KEY(KEY_NAME, KEY_TYPE) +//%DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, , POD) +//%DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, Object, id) + +//%PDDM-DEFINE DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt32, uint32_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int32, int32_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt64, uint64_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int64, int64_t, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Bool, BOOL, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Float, float, KHELPER) +//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Double, double, KHELPER) +//%DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, Enum, int32_t, KHELPER) + +//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER) +//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD, VALUE_NAME, value) + +//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, , VALUE_NAME, VALUE_TYPE, POD, OBJECT, Object, object) + +//%PDDM-DEFINE DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary { +//% @package +//% NSMutableDictionary *_dictionary; +//%} +//% +//%- (instancetype)init { +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%- (instancetype)initWith##VNAME##s:(const VALUE_TYPE [])##VNAME_VAR##s +//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP [])keys +//% ##VNAME$S## count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% _dictionary = [[NSMutableDictionary alloc] init]; +//% if (count && VNAME_VAR##s && keys) { +//% for (NSUInteger i = 0; i < count; ++i) { +//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME_VAR##s[i], ______)##DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______) [_dictionary setObject:WRAPPED##VHELPER(VNAME_VAR##s[i]) forKey:WRAPPED##KHELPER(keys[i])]; +//% } +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//% if (self) { +//% if (dictionary) { +//% [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithCapacity:(NSUInteger)numItems { +//% #pragma unused(numItems) +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ) +//% +//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_NAME, VALUE_TYPE, KHELPER) +//% +//%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ) +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER) +//%DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD) +//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER) +//%#pragma mark - KEY_NAME -> VALUE_NAME +//% +//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary { +//% @package +//% NSMutableDictionary *_dictionary; +//% GPBEnumValidationFunc _validationFunc; +//%} +//% +//%@synthesize validationFunc = _validationFunc; +//% +//%- (instancetype)init { +//% return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +//%} +//% +//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { +//% return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +//%} +//% +//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//% rawValues:(const VALUE_TYPE [])rawValues +//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys +//% count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% _dictionary = [[NSMutableDictionary alloc] init]; +//% _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); +//% if (count && rawValues && keys) { +//% for (NSUInteger i = 0; i < count; ++i) { +//%DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______) [_dictionary setObject:WRAPPED##VHELPER(rawValues[i]) forKey:WRAPPED##KHELPER(keys[i])]; +//% } +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWithValidationFunction:dictionary.validationFunc +//% rawValues:NULL +//% forKeys:NULL +//% count:0]; +//% if (self) { +//% if (dictionary) { +//% [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//% capacity:(NSUInteger)numItems { +//% #pragma unused(numItems) +//% return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +//%} +//% +//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Value, value, Raw) +//% +//%- (BOOL)getEnum:(VALUE_TYPE *)value forKey:(KEY_TYPE##KisP$S##KisP)key { +//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% if (wrapped && value) { +//% VALUE_TYPE result = UNWRAP##VALUE_NAME(wrapped); +//% if (!_validationFunc(result)) { +//% result = kGPBUnrecognizedEnumeratorValue; +//% } +//% *value = result; +//% } +//% return (wrapped != NULL); +//%} +//% +//%- (BOOL)getRawValue:(VALUE_TYPE *)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key { +//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% if (wrapped && rawValue) { +//% *rawValue = UNWRAP##VALUE_NAME(wrapped); +//% } +//% return (wrapped != NULL); +//%} +//% +//%- (void)enumerateKeysAndEnumsUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block { +//% GPBEnumValidationFunc func = _validationFunc; +//% BOOL stop = NO; +//% NSEnumerator *keys = [_dictionary keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue = _dictionary[aKey]; +//% VALUE_TYPE unwrapped = UNWRAP##VALUE_NAME(aValue); +//% if (!func(unwrapped)) { +//% unwrapped = kGPBUnrecognizedEnumeratorValue; +//% } +//% block(UNWRAP##KEY_NAME(aKey), unwrapped, &stop); +//% if (stop) { +//% break; +//% } +//% } +//%} +//% +//%DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Value, Enum, value, Raw) +//% +//%- (void)setEnum:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key { +//%DICTIONARY_VALIDATE_KEY_##KHELPER(key, ) if (!_validationFunc(value)) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"GPB##KEY_NAME##VALUE_NAME##Dictionary: Attempt to set an unknown enum value (%d)", +//% value]; +//% } +//% +//% [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%@end +//% + +//%PDDM-DEFINE DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ACCESSOR_NAME) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [_dictionary release]; +//% [super dealloc]; +//%} +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { +//% return [[GPB##KEY_NAME##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self]; +//%} +//% +//%- (BOOL)isEqual:(id)other { +//% if (self == other) { +//% return YES; +//% } +//% if (![other isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]) { +//% return NO; +//% } +//% GPB##KEY_NAME##VALUE_NAME##Dictionary *otherDictionary = other; +//% return [_dictionary isEqual:otherDictionary->_dictionary]; +//%} +//% +//%- (NSUInteger)hash { +//% return _dictionary.count; +//%} +//% +//%- (NSString *)description { +//% return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +//%} +//% +//%- (NSUInteger)count { +//% return _dictionary.count; +//%} +//% +//%- (void)enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock: +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { +//% BOOL stop = NO; +//% NSDictionary *internal = _dictionary; +//% NSEnumerator *keys = [internal keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey]; +//% block(UNWRAP##KEY_NAME(aKey), UNWRAP##VALUE_NAME(a##VNAME_VAR$u), &stop); +//% if (stop) { +//% break; +//% } +//% } +//%} +//% +//%EXTRA_METHODS_##VHELPER(KEY_NAME, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { +//% NSDictionary *internal = _dictionary; +//% NSUInteger count = internal.count; +//% if (count == 0) { +//% return 0; +//% } +//% +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; +//% size_t result = 0; +//% NSEnumerator *keys = [internal keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey]; +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(a##VNAME_VAR$u), kMapValueFieldNumber, valueDataType); +//% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; +//% } +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); +//% result += tagSize * count; +//% return result; +//%} +//% +//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream +//% asField:(GPBFieldDescriptor *)field { +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; +//% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); +//% NSDictionary *internal = _dictionary; +//% NSEnumerator *keys = [internal keyEnumerator]; +//% ENUM_TYPE##KHELPER(KEY_TYPE)##aKey; +//% while ((aKey = [keys nextObject])) { +//% ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey]; +//% [outputStream writeInt32NoTag:tag]; +//% // Write the size of the message. +//% KEY_TYPE KisP##unwrappedKey = UNWRAP##KEY_NAME(aKey); +//% VALUE_TYPE unwrappedValue = UNWRAP##VALUE_NAME(a##VNAME_VAR$u); +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); +//% [outputStream writeInt32NoTag:(int32_t)msgSize]; +//% // Write the fields. +//% WriteDict##KEY_NAME##Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); +//% WriteDict##VALUE_NAME##Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); +//% } +//%} +//% +//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { +//% [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)]; +//%} +//% +//%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { +//% [self enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop) { +//% #pragma unused(stop) +//% block(TEXT_FORMAT_OBJ##KEY_NAME(key), TEXT_FORMAT_OBJ##VALUE_NAME(VNAME_VAR)); +//% }]; +//%} +//%PDDM-DEFINE DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_VAR, ACCESSOR_NAME) +//%DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME, VNAME_VAR, ACCESSOR_NAME) +//%PDDM-DEFINE DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, VNAME_REMOVE, VNAME_VAR, ACCESSOR_NAME) +//%- (void)add##ACCESSOR_NAME##EntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary { +//% if (otherDictionary) { +//% [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//% } +//%} +//% +//%- (void)set##ACCESSOR_NAME##VNAME##:(VALUE_TYPE)VNAME_VAR forKey:(KEY_TYPE##KisP$S##KisP)key { +//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME_VAR, )##DICTIONARY_VALIDATE_KEY_##KHELPER(key, ) [_dictionary setObject:WRAPPED##VHELPER(VNAME_VAR) forKey:WRAPPED##KHELPER(key)]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%- (void)remove##VNAME_REMOVE##ForKey:(KEY_TYPE##KisP$S##KisP)aKey { +//% [_dictionary removeObjectForKey:WRAPPED##KHELPER(aKey)]; +//%} +//% +//%- (void)removeAll { +//% [_dictionary removeAllObjects]; +//%} + +// +// Custom Generation for Bool keys +// + +//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_POD_IMPL(VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, POD, VALUE_NAME, value) +//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(VALUE_NAME, VALUE_TYPE) +//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, OBJECT, Object, object) + +//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, HELPER, VNAME, VNAME_VAR) +//%#pragma mark - Bool -> VALUE_NAME +//% +//%@implementation GPBBool##VALUE_NAME##Dictionary { +//% @package +//% VALUE_TYPE _values[2]; +//%BOOL_DICT_HAS_STORAGE_##HELPER()} +//% +//%- (instancetype)init { +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%BOOL_DICT_INITS_##HELPER(VALUE_NAME, VALUE_TYPE) +//% +//%- (instancetype)initWithCapacity:(NSUInteger)numItems { +//% #pragma unused(numItems) +//% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; +//%} +//% +//%BOOL_DICT_DEALLOC##HELPER() +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { +//% return [[GPBBool##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self]; +//%} +//% +//%- (BOOL)isEqual:(id)other { +//% if (self == other) { +//% return YES; +//% } +//% if (![other isKindOfClass:[GPBBool##VALUE_NAME##Dictionary class]]) { +//% return NO; +//% } +//% GPBBool##VALUE_NAME##Dictionary *otherDictionary = other; +//% if ((BOOL_DICT_W_HAS##HELPER(0, ) != BOOL_DICT_W_HAS##HELPER(0, otherDictionary->)) || +//% (BOOL_DICT_W_HAS##HELPER(1, ) != BOOL_DICT_W_HAS##HELPER(1, otherDictionary->))) { +//% return NO; +//% } +//% if ((BOOL_DICT_W_HAS##HELPER(0, ) && (NEQ_##HELPER(_values[0], otherDictionary->_values[0]))) || +//% (BOOL_DICT_W_HAS##HELPER(1, ) && (NEQ_##HELPER(_values[1], otherDictionary->_values[1])))) { +//% return NO; +//% } +//% return YES; +//%} +//% +//%- (NSUInteger)hash { +//% return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0); +//%} +//% +//%- (NSString *)description { +//% NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; +//% if (BOOL_DICT_W_HAS##HELPER(0, )) { +//% [result appendFormat:@"NO: STR_FORMAT_##HELPER(VALUE_NAME)", _values[0]]; +//% } +//% if (BOOL_DICT_W_HAS##HELPER(1, )) { +//% [result appendFormat:@"YES: STR_FORMAT_##HELPER(VALUE_NAME)", _values[1]]; +//% } +//% [result appendString:@" }"]; +//% return result; +//%} +//% +//%- (NSUInteger)count { +//% return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0); +//%} +//% +//%BOOL_VALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE) +//% +//%BOOL_SET_GPBVALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE, VisP) +//% +//%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { +//% if (BOOL_DICT_HAS##HELPER(0, )) { +//% block(@"false", TEXT_FORMAT_OBJ##VALUE_NAME(_values[0])); +//% } +//% if (BOOL_DICT_W_HAS##HELPER(1, )) { +//% block(@"true", TEXT_FORMAT_OBJ##VALUE_NAME(_values[1])); +//% } +//%} +//% +//%- (void)enumerateKeysAnd##VNAME##sUsingBlock: +//% (void (NS_NOESCAPE ^)(BOOL key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { +//% BOOL stop = NO; +//% if (BOOL_DICT_HAS##HELPER(0, )) { +//% block(NO, _values[0], &stop); +//% } +//% if (!stop && BOOL_DICT_W_HAS##HELPER(1, )) { +//% block(YES, _values[1], &stop); +//% } +//%} +//% +//%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% NSUInteger count = 0; +//% size_t result = 0; +//% for (int i = 0; i < 2; ++i) { +//% if (BOOL_DICT_HAS##HELPER(i, )) { +//% ++count; +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); +//% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; +//% } +//% } +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); +//% result += tagSize * count; +//% return result; +//%} +//% +//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream +//% asField:(GPBFieldDescriptor *)field { +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); +//% for (int i = 0; i < 2; ++i) { +//% if (BOOL_DICT_HAS##HELPER(i, )) { +//% // Write the tag. +//% [outputStream writeInt32NoTag:tag]; +//% // Write the size of the message. +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); +//% [outputStream writeInt32NoTag:(int32_t)msgSize]; +//% // Write the fields. +//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); +//% } +//% } +//%} +//% +//%BOOL_DICT_MUTATIONS_##HELPER(VALUE_NAME, VALUE_TYPE) +//% +//%@end +//% + + +// +// Helpers for PODs +// + +//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER) +//%- (BOOL)get##VALUE_NAME##:(nullable VALUE_TYPE *)value forKey:(KEY_TYPE)key { +//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% if (wrapped && value) { +//% *value = UNWRAP##VALUE_NAME(wrapped); +//% } +//% return (wrapped != NULL); +//%} +//%PDDM-DEFINE WRAPPEDPOD(VALUE) +//%@(VALUE) +//%PDDM-DEFINE UNWRAPUInt32(VALUE) +//%[VALUE unsignedIntValue] +//%PDDM-DEFINE UNWRAPInt32(VALUE) +//%[VALUE intValue] +//%PDDM-DEFINE UNWRAPUInt64(VALUE) +//%[VALUE unsignedLongLongValue] +//%PDDM-DEFINE UNWRAPInt64(VALUE) +//%[VALUE longLongValue] +//%PDDM-DEFINE UNWRAPBool(VALUE) +//%[VALUE boolValue] +//%PDDM-DEFINE UNWRAPFloat(VALUE) +//%[VALUE floatValue] +//%PDDM-DEFINE UNWRAPDouble(VALUE) +//%[VALUE doubleValue] +//%PDDM-DEFINE UNWRAPEnum(VALUE) +//%[VALUE intValue] +//%PDDM-DEFINE TEXT_FORMAT_OBJUInt32(VALUE) +//%[NSString stringWithFormat:@"%u", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJInt32(VALUE) +//%[NSString stringWithFormat:@"%d", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJUInt64(VALUE) +//%[NSString stringWithFormat:@"%llu", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJInt64(VALUE) +//%[NSString stringWithFormat:@"%lld", VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJBool(VALUE) +//%(VALUE ? @"true" : @"false") +//%PDDM-DEFINE TEXT_FORMAT_OBJFloat(VALUE) +//%[NSString stringWithFormat:@"%.*g", FLT_DIG, VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJDouble(VALUE) +//%[NSString stringWithFormat:@"%.*lg", DBL_DIG, VALUE] +//%PDDM-DEFINE TEXT_FORMAT_OBJEnum(VALUE) +//%@(VALUE) +//%PDDM-DEFINE ENUM_TYPEPOD(TYPE) +//%NSNumber * +//%PDDM-DEFINE NEQ_POD(VAL1, VAL2) +//%VAL1 != VAL2 +//%PDDM-DEFINE EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME) +// Empty +//%PDDM-DEFINE BOOL_EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD(KEY_NAME, VALUE_NAME) +//%SERIAL_DATA_FOR_ENTRY_POD_##VALUE_NAME(KEY_NAME) +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt32(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int32(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt64(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int64(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Bool(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Float(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Double(KEY_NAME) +// Empty +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Enum(KEY_NAME) +//%- (NSData *)serializedDataForUnknownValue:(int32_t)value +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType { +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); +//% NSMutableData *data = [NSMutableData dataWithLength:msgSize]; +//% GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; +//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); +//% [outputStream release]; +//% return data; +//%} +//% +//%PDDM-DEFINE GPBVALUE_POD(VALUE_NAME) +//%value##VALUE_NAME +//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_POD(VALUE_NAME, EXTRA_INDENT) +// Empty +//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_POD(KEY_NAME, EXTRA_INDENT) +// Empty + +//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_POD() +//% BOOL _valueSet[2]; +//% +//%PDDM-DEFINE BOOL_DICT_INITS_POD(VALUE_NAME, VALUE_TYPE) +//%- (instancetype)initWith##VALUE_NAME##s:(const VALUE_TYPE [])values +//% ##VALUE_NAME$S## forKeys:(const BOOL [])keys +//% ##VALUE_NAME$S## count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% for (NSUInteger i = 0; i < count; ++i) { +//% int idx = keys[i] ? 1 : 0; +//% _values[idx] = values[i]; +//% _valueSet[idx] = YES; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWith##VALUE_NAME##s:NULL forKeys:NULL count:0]; +//% if (self) { +//% if (dictionary) { +//% for (int i = 0; i < 2; ++i) { +//% if (dictionary->_valueSet[i]) { +//% _values[i] = dictionary->_values[i]; +//% _valueSet[i] = YES; +//% } +//% } +//% } +//% } +//% return self; +//%} +//%PDDM-DEFINE BOOL_DICT_DEALLOCPOD() +//%#if !defined(NS_BLOCK_ASSERTIONS) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [super dealloc]; +//%} +//%#endif // !defined(NS_BLOCK_ASSERTIONS) +//%PDDM-DEFINE BOOL_DICT_W_HASPOD(IDX, REF) +//%BOOL_DICT_HASPOD(IDX, REF) +//%PDDM-DEFINE BOOL_DICT_HASPOD(IDX, REF) +//%REF##_valueSet[IDX] +//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE) +//%- (BOOL)get##VALUE_NAME##:(VALUE_TYPE *)value forKey:(BOOL)key { +//% int idx = (key ? 1 : 0); +//% if (_valueSet[idx]) { +//% if (value) { +//% *value = _values[idx]; +//% } +//% return YES; +//% } +//% return NO; +//%} +//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP) +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { +//% int idx = (key->valueBool ? 1 : 0); +//% _values[idx] = value->value##VALUE_NAME; +//% _valueSet[idx] = YES; +//%} +//%PDDM-DEFINE BOOL_DICT_MUTATIONS_POD(VALUE_NAME, VALUE_TYPE) +//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary { +//% if (otherDictionary) { +//% for (int i = 0; i < 2; ++i) { +//% if (otherDictionary->_valueSet[i]) { +//% _valueSet[i] = YES; +//% _values[i] = otherDictionary->_values[i]; +//% } +//% } +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//% } +//%} +//% +//%- (void)set##VALUE_NAME:(VALUE_TYPE)value forKey:(BOOL)key { +//% int idx = (key ? 1 : 0); +//% _values[idx] = value; +//% _valueSet[idx] = YES; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%- (void)remove##VALUE_NAME##ForKey:(BOOL)aKey { +//% _valueSet[aKey ? 1 : 0] = NO; +//%} +//% +//%- (void)removeAll { +//% _valueSet[0] = NO; +//% _valueSet[1] = NO; +//%} +//%PDDM-DEFINE STR_FORMAT_POD(VALUE_NAME) +//%STR_FORMAT_##VALUE_NAME() +//%PDDM-DEFINE STR_FORMAT_UInt32() +//%%u +//%PDDM-DEFINE STR_FORMAT_Int32() +//%%d +//%PDDM-DEFINE STR_FORMAT_UInt64() +//%%llu +//%PDDM-DEFINE STR_FORMAT_Int64() +//%%lld +//%PDDM-DEFINE STR_FORMAT_Bool() +//%%d +//%PDDM-DEFINE STR_FORMAT_Float() +//%%f +//%PDDM-DEFINE STR_FORMAT_Double() +//%%lf + +// +// Helpers for Objects +// + +//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER) +//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key { +//% VALUE_TYPE result = [_dictionary objectForKey:WRAPPED##KHELPER(key)]; +//% return result; +//%} +//%PDDM-DEFINE WRAPPEDOBJECT(VALUE) +//%VALUE +//%PDDM-DEFINE UNWRAPString(VALUE) +//%VALUE +//%PDDM-DEFINE UNWRAPObject(VALUE) +//%VALUE +//%PDDM-DEFINE TEXT_FORMAT_OBJString(VALUE) +//%VALUE +//%PDDM-DEFINE TEXT_FORMAT_OBJObject(VALUE) +//%VALUE +//%PDDM-DEFINE ENUM_TYPEOBJECT(TYPE) +//%ENUM_TYPEOBJECT_##TYPE() +//%PDDM-DEFINE ENUM_TYPEOBJECT_NSString() +//%NSString * +//%PDDM-DEFINE ENUM_TYPEOBJECT_id() +//%id ## +//%PDDM-DEFINE NEQ_OBJECT(VAL1, VAL2) +//%![VAL1 isEqual:VAL2] +//%PDDM-DEFINE EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME) +//%- (BOOL)isInitialized { +//% for (GPBMessage *msg in [_dictionary objectEnumerator]) { +//% if (!msg.initialized) { +//% return NO; +//% } +//% } +//% return YES; +//%} +//% +//%- (instancetype)deepCopyWithZone:(NSZone *)zone { +//% GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict = +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; +//% NSEnumerator *keys = [_dictionary keyEnumerator]; +//% id aKey; +//% NSMutableDictionary *internalDict = newDict->_dictionary; +//% while ((aKey = [keys nextObject])) { +//% GPBMessage *msg = _dictionary[aKey]; +//% GPBMessage *copiedMsg = [msg copyWithZone:zone]; +//% [internalDict setObject:copiedMsg forKey:aKey]; +//% [copiedMsg release]; +//% } +//% return newDict; +//%} +//% +//% +//%PDDM-DEFINE BOOL_EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME) +//%- (BOOL)isInitialized { +//% if (_values[0] && ![_values[0] isInitialized]) { +//% return NO; +//% } +//% if (_values[1] && ![_values[1] isInitialized]) { +//% return NO; +//% } +//% return YES; +//%} +//% +//%- (instancetype)deepCopyWithZone:(NSZone *)zone { +//% GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict = +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; +//% for (int i = 0; i < 2; ++i) { +//% if (_values[i] != nil) { +//% newDict->_values[i] = [_values[i] copyWithZone:zone]; +//% } +//% } +//% return newDict; +//%} +//% +//% +//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_OBJECT(KEY_NAME, VALUE_NAME) +// Empty +//%PDDM-DEFINE GPBVALUE_OBJECT(VALUE_NAME) +//%valueString +//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_OBJECT(VALUE_NAME, EXTRA_INDENT) +//%##EXTRA_INDENT$S## if (!##VALUE_NAME) { +//%##EXTRA_INDENT$S## [NSException raise:NSInvalidArgumentException +//%##EXTRA_INDENT$S## format:@"Attempting to add nil object to a Dictionary"]; +//%##EXTRA_INDENT$S## } +//% +//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_OBJECT(KEY_NAME, EXTRA_INDENT) +//%##EXTRA_INDENT$S## if (!##KEY_NAME) { +//%##EXTRA_INDENT$S## [NSException raise:NSInvalidArgumentException +//%##EXTRA_INDENT$S## format:@"Attempting to add nil key to a Dictionary"]; +//%##EXTRA_INDENT$S## } +//% + +//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_OBJECT() +// Empty +//%PDDM-DEFINE BOOL_DICT_INITS_OBJECT(VALUE_NAME, VALUE_TYPE) +//%- (instancetype)initWithObjects:(const VALUE_TYPE [])objects +//% forKeys:(const BOOL [])keys +//% count:(NSUInteger)count { +//% self = [super init]; +//% if (self) { +//% for (NSUInteger i = 0; i < count; ++i) { +//% if (!objects[i]) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"Attempting to add nil object to a Dictionary"]; +//% } +//% int idx = keys[i] ? 1 : 0; +//% [_values[idx] release]; +//% _values[idx] = (VALUE_TYPE)[objects[i] retain]; +//% } +//% } +//% return self; +//%} +//% +//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary { +//% self = [self initWithObjects:NULL forKeys:NULL count:0]; +//% if (self) { +//% if (dictionary) { +//% _values[0] = [dictionary->_values[0] retain]; +//% _values[1] = [dictionary->_values[1] retain]; +//% } +//% } +//% return self; +//%} +//%PDDM-DEFINE BOOL_DICT_DEALLOCOBJECT() +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [_values[0] release]; +//% [_values[1] release]; +//% [super dealloc]; +//%} +//%PDDM-DEFINE BOOL_DICT_W_HASOBJECT(IDX, REF) +//%(BOOL_DICT_HASOBJECT(IDX, REF)) +//%PDDM-DEFINE BOOL_DICT_HASOBJECT(IDX, REF) +//%REF##_values[IDX] != nil +//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE) +//%- (VALUE_TYPE)objectForKey:(BOOL)key { +//% return _values[key ? 1 : 0]; +//%} +//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE, VisP) +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { +//% int idx = (key->valueBool ? 1 : 0); +//% [_values[idx] release]; +//% _values[idx] = [value->valueString retain]; +//%} + +//%PDDM-DEFINE BOOL_DICT_MUTATIONS_OBJECT(VALUE_NAME, VALUE_TYPE) +//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary { +//% if (otherDictionary) { +//% for (int i = 0; i < 2; ++i) { +//% if (otherDictionary->_values[i] != nil) { +//% [_values[i] release]; +//% _values[i] = [otherDictionary->_values[i] retain]; +//% } +//% } +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//% } +//%} +//% +//%- (void)setObject:(VALUE_TYPE)object forKey:(BOOL)key { +//% if (!object) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"Attempting to add nil object to a Dictionary"]; +//% } +//% int idx = (key ? 1 : 0); +//% [_values[idx] release]; +//% _values[idx] = [object retain]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } +//%} +//% +//%- (void)removeObjectForKey:(BOOL)aKey { +//% int idx = (aKey ? 1 : 0); +//% [_values[idx] release]; +//% _values[idx] = nil; +//%} +//% +//%- (void)removeAll { +//% for (int i = 0; i < 2; ++i) { +//% [_values[i] release]; +//% _values[i] = nil; +//% } +//%} +//%PDDM-DEFINE STR_FORMAT_OBJECT(VALUE_NAME) +//%%@ + + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt32 -> UInt32 + +@implementation GPBUInt32UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32UInt32Dictionary class]]) { + return NO; + } + GPBUInt32UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(uint32_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Int32 + +@implementation GPBUInt32Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32Int32Dictionary class]]) { + return NO; + } + GPBUInt32Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> UInt64 + +@implementation GPBUInt32UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32UInt64Dictionary class]]) { + return NO; + } + GPBUInt32UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(uint32_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Int64 + +@implementation GPBUInt32Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32Int64Dictionary class]]) { + return NO; + } + GPBUInt32Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(uint32_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Bool + +@implementation GPBUInt32BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32BoolDictionary class]]) { + return NO; + } + GPBUInt32BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(uint32_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Float + +@implementation GPBUInt32FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32FloatDictionary class]]) { + return NO; + } + GPBUInt32FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(uint32_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Double + +@implementation GPBUInt32DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32DoubleDictionary class]]) { + return NO; + } + GPBUInt32DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(uint32_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt32 -> Enum + +@implementation GPBUInt32EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32EnumDictionary class]]) { + return NO; + } + GPBUInt32EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedIntValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(uint32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey unsignedIntValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(uint32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(uint32_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBUInt32EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - UInt32 -> Object + +@implementation GPBUInt32ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const uint32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt32ObjectDictionary class]]) { + return NO; + } + GPBUInt32ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint32_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey unsignedIntValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBUInt32ObjectDictionary *newDict = + [[GPBUInt32ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint32_t unwrappedKey = [aKey unsignedIntValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(uint32_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%u", key], object); + }]; +} + +- (id)objectForKey:(uint32_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(uint32_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(uint32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int32 -> UInt32 + +@implementation GPBInt32UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32UInt32Dictionary class]]) { + return NO; + } + GPBInt32UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(int32_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Int32 + +@implementation GPBInt32Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32Int32Dictionary class]]) { + return NO; + } + GPBInt32Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(int32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> UInt64 + +@implementation GPBInt32UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32UInt64Dictionary class]]) { + return NO; + } + GPBInt32UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(int32_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Int64 + +@implementation GPBInt32Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32Int64Dictionary class]]) { + return NO; + } + GPBInt32Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(int32_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Bool + +@implementation GPBInt32BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32BoolDictionary class]]) { + return NO; + } + GPBInt32BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(int32_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Float + +@implementation GPBInt32FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32FloatDictionary class]]) { + return NO; + } + GPBInt32FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(int32_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Double + +@implementation GPBInt32DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32DoubleDictionary class]]) { + return NO; + } + GPBInt32DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(int32_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int32 -> Enum + +@implementation GPBInt32EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32EnumDictionary class]]) { + return NO; + } + GPBInt32EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey intValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(int32_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey intValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(int32_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(int32_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBInt32EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - Int32 -> Object + +@implementation GPBInt32ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const int32_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt32ObjectDictionary class]]) { + return NO; + } + GPBInt32ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int32_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey intValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBInt32ObjectDictionary *newDict = + [[GPBInt32ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int32_t unwrappedKey = [aKey intValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueInt32)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(int32_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%d", key], object); + }]; +} + +- (id)objectForKey:(int32_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(int32_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(int32_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - UInt64 -> UInt32 + +@implementation GPBUInt64UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64UInt32Dictionary class]]) { + return NO; + } + GPBUInt64UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(uint64_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Int32 + +@implementation GPBUInt64Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64Int32Dictionary class]]) { + return NO; + } + GPBUInt64Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> UInt64 + +@implementation GPBUInt64UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64UInt64Dictionary class]]) { + return NO; + } + GPBUInt64UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(uint64_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Int64 + +@implementation GPBUInt64Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64Int64Dictionary class]]) { + return NO; + } + GPBUInt64Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(uint64_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Bool + +@implementation GPBUInt64BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64BoolDictionary class]]) { + return NO; + } + GPBUInt64BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(uint64_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Float + +@implementation GPBUInt64FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64FloatDictionary class]]) { + return NO; + } + GPBUInt64FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(uint64_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Double + +@implementation GPBUInt64DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64DoubleDictionary class]]) { + return NO; + } + GPBUInt64DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(uint64_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - UInt64 -> Enum + +@implementation GPBUInt64EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64EnumDictionary class]]) { + return NO; + } + GPBUInt64EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey unsignedLongLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(uint64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey unsignedLongLongValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(uint64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(uint64_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBUInt64EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - UInt64 -> Object + +@implementation GPBUInt64ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const uint64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBUInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBUInt64ObjectDictionary class]]) { + return NO; + } + GPBUInt64ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(uint64_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey unsignedLongLongValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBUInt64ObjectDictionary *newDict = + [[GPBUInt64ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + uint64_t unwrappedKey = [aKey unsignedLongLongValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(uint64_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%llu", key], object); + }]; +} + +- (id)objectForKey:(uint64_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(uint64_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(uint64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Int64 -> UInt32 + +@implementation GPBInt64UInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64UInt32Dictionary class]]) { + return NO; + } + GPBInt64UInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(int64_t key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Int32 + +@implementation GPBInt64Int32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64Int32Dictionary class]]) { + return NO; + } + GPBInt64Int32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(int64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> UInt64 + +@implementation GPBInt64UInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64UInt64Dictionary class]]) { + return NO; + } + GPBInt64UInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(int64_t key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Int64 + +@implementation GPBInt64Int64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64Int64Dictionary class]]) { + return NO; + } + GPBInt64Int64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(int64_t key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Bool + +@implementation GPBInt64BoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64BoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64BoolDictionary class]]) { + return NO; + } + GPBInt64BoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(int64_t key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Float + +@implementation GPBInt64FloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64FloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64FloatDictionary class]]) { + return NO; + } + GPBInt64FloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(int64_t key, float value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Double + +@implementation GPBInt64DoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(values[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64DoubleDictionary class]]) { + return NO; + } + GPBInt64DoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(int64_t key, double value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - Int64 -> Enum + +@implementation GPBInt64EnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64EnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64EnumDictionary class]]) { + return NO; + } + GPBInt64EnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block([aKey longLongValue], [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(int64_t)key { + NSNumber *wrapped = [_dictionary objectForKey:@(key)]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block([aKey longLongValue], unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(int64_t)key { + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(int64_t)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBInt64EnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +#pragma mark - Int64 -> Object + +@implementation GPBInt64ObjectDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const int64_t [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && objects && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:objects[i] forKey:@(keys[i])]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBInt64ObjectDictionary class]]) { + return NO; + } + GPBInt64ObjectDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(int64_t key, id object, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + block([aKey longLongValue], aObject, &stop); + if (stop) { + break; + } + } +} + +- (BOOL)isInitialized { + for (GPBMessage *msg in [_dictionary objectEnumerator]) { + if (!msg.initialized) { + return NO; + } + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBInt64ObjectDictionary *newDict = + [[GPBInt64ObjectDictionary alloc] init]; + NSEnumerator *keys = [_dictionary keyEnumerator]; + id aKey; + NSMutableDictionary *internalDict = newDict->_dictionary; + while ((aKey = [keys nextObject])) { + GPBMessage *msg = _dictionary[aKey]; + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [internalDict setObject:copiedMsg forKey:aKey]; + [copiedMsg release]; + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSNumber *aKey; + while ((aKey = [keys nextObject])) { + id aObject = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + int64_t unwrappedKey = [aKey longLongValue]; + id unwrappedValue = aObject; + size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:value->valueString forKey:@(key->valueInt64)]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndObjectsUsingBlock:^(int64_t key, id object, BOOL *stop) { + #pragma unused(stop) + block([NSString stringWithFormat:@"%lld", key], object); + }]; +} + +- (id)objectForKey:(int64_t)key { + id result = [_dictionary objectForKey:@(key)]; + return result; +} + +- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(int64_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + [_dictionary setObject:object forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(int64_t)aKey { + [_dictionary removeObjectForKey:@(aKey)]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +//%PDDM-EXPAND DICTIONARY_POD_IMPL_FOR_KEY(String, NSString, *, OBJECT) +// This block of code is generated, do not edit it directly. + +#pragma mark - String -> UInt32 + +@implementation GPBStringUInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringUInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringUInt32Dictionary class]]) { + return NO; + } + GPBStringUInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue unsignedIntValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + uint32_t unwrappedValue = [aValue unsignedIntValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt32sUsingBlock:^(NSString *key, uint32_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%u", value]); + }]; +} + +- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped unsignedIntValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Int32 + +@implementation GPBStringInt32Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringInt32Dictionary class]]) { + return NO; + } + GPBStringInt32Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt32) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt32sUsingBlock:^(NSString *key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%d", value]); + }]; +} + +- (BOOL)getInt32:(nullable int32_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> UInt64 + +@implementation GPBStringUInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringUInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringUInt64Dictionary class]]) { + return NO; + } + GPBStringUInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue unsignedLongLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + uint64_t unwrappedValue = [aValue unsignedLongLongValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndUInt64sUsingBlock:^(NSString *key, uint64_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%llu", value]); + }]; +} + +- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped unsignedLongLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Int64 + +@implementation GPBStringInt64Dictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringInt64Dictionary class]]) { + return NO; + } + GPBStringInt64Dictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue longLongValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + int64_t unwrappedValue = [aValue longLongValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueInt64) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndInt64sUsingBlock:^(NSString *key, int64_t value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%lld", value]); + }]; +} + +- (BOOL)getInt64:(nullable int64_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped longLongValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Bool + +@implementation GPBStringBoolDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringBoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringBoolDictionary class]]) { + return NO; + } + GPBStringBoolDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue boolValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + BOOL unwrappedValue = [aValue boolValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueBool) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndBoolsUsingBlock:^(NSString *key, BOOL value, BOOL *stop) { + #pragma unused(stop) + block(key, (value ? @"true" : @"false")); + }]; +} + +- (BOOL)getBool:(nullable BOOL *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped boolValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Float + +@implementation GPBStringFloatDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringFloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringFloatDictionary class]]) { + return NO; + } + GPBStringFloatDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, float value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue floatValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + float unwrappedValue = [aValue floatValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueFloat) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndFloatsUsingBlock:^(NSString *key, float value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); + }]; +} + +- (BOOL)getFloat:(nullable float *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped floatValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Double + +@implementation GPBStringDoubleDictionary { + @package + NSMutableDictionary *_dictionary; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + if (count && values && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(values[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringDoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringDoubleDictionary class]]) { + return NO; + } + GPBStringDoubleDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, double value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue doubleValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + double unwrappedValue = [aValue doubleValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueDouble) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndDoublesUsingBlock:^(NSString *key, double value, BOOL *stop) { + #pragma unused(stop) + block(key, [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); + }]; +} + +- (BOOL)getDouble:(nullable double *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + *value = [wrapped doubleValue]; + } + return (wrapped != NULL); +} + +- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +@end + +#pragma mark - String -> Enum + +@implementation GPBStringEnumDictionary { + @package + NSMutableDictionary *_dictionary; + GPBEnumValidationFunc _validationFunc; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const NSString * [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] init]; + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + if (count && rawValues && keys) { + for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(rawValues[i]) forKey:keys[i]]; + } + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + [_dictionary addEntriesFromDictionary:dictionary->_dictionary]; + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBStringEnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBStringEnumDictionary class]]) { + return NO; + } + GPBStringEnumDictionary *otherDictionary = other; + return [_dictionary isEqual:otherDictionary->_dictionary]; +} + +- (NSUInteger)hash { + return _dictionary.count; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary]; +} + +- (NSUInteger)count { + return _dictionary.count; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + block(aKey, [aValue intValue], &stop); + if (stop) { + break; + } + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + NSDictionary *internal = _dictionary; + NSUInteger count = internal.count; + if (count == 0) { + return 0; + } + + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + size_t result = 0; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + NSDictionary *internal = _dictionary; + NSEnumerator *keys = [internal keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = internal[aKey]; + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + NSString *unwrappedKey = aKey; + int32_t unwrappedValue = [aValue intValue]; + size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType); + } +} + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + [_dictionary setObject:@(value->valueEnum) forKey:key->valueString]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) { + #pragma unused(stop) + block(key, @(value)); + }]; +} + +- (BOOL)getEnum:(int32_t *)value forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && value) { + int32_t result = [wrapped intValue]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return (wrapped != NULL); +} + +- (BOOL)getRawValue:(int32_t *)rawValue forKey:(NSString *)key { + NSNumber *wrapped = [_dictionary objectForKey:key]; + if (wrapped && rawValue) { + *rawValue = [wrapped intValue]; + } + return (wrapped != NULL); +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { + GPBEnumValidationFunc func = _validationFunc; + BOOL stop = NO; + NSEnumerator *keys = [_dictionary keyEnumerator]; + NSString *aKey; + while ((aKey = [keys nextObject])) { + NSNumber *aValue = _dictionary[aKey]; + int32_t unwrapped = [aValue intValue]; + if (!func(unwrapped)) { + unwrapped = kGPBUnrecognizedEnumeratorValue; + } + block(aKey, unwrapped, &stop); + if (stop) { + break; + } + } +} + +- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary { + if (otherDictionary) { + [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setRawValue:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(NSString *)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +- (void)removeAll { + [_dictionary removeAllObjects]; +} + +- (void)setEnum:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBStringEnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + + [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +@end + +//%PDDM-EXPAND-END (5 expansions) + + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> UInt32 + +@implementation GPBBoolUInt32Dictionary { + @package + uint32_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt32s:(const uint32_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary { + self = [self initWithUInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt32s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolUInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolUInt32Dictionary class]]) { + return NO; + } + GPBBoolUInt32Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %u", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %u", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getUInt32:(uint32_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueUInt32; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%u", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%u", _values[1]]); + } +} + +- (void)enumerateKeysAndUInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint32_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt32:(uint32_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt32ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Int32 + +@implementation GPBBoolInt32Dictionary { + @package + int32_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt32s:(const int32_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary { + self = [self initWithInt32s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt32s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolInt32Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolInt32Dictionary class]]) { + return NO; + } + GPBBoolInt32Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %d", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %d", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getInt32:(int32_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueInt32; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%d", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%d", _values[1]]); + } +} + +- (void)enumerateKeysAndInt32sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt32:(int32_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt32ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> UInt64 + +@implementation GPBBoolUInt64Dictionary { + @package + uint64_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithUInt64s:(const uint64_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary { + self = [self initWithUInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithUInt64s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolUInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolUInt64Dictionary class]]) { + return NO; + } + GPBBoolUInt64Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %llu", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %llu", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getUInt64:(uint64_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueUInt64; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%llu", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%llu", _values[1]]); + } +} + +- (void)enumerateKeysAndUInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, uint64_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setUInt64:(uint64_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeUInt64ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Int64 + +@implementation GPBBoolInt64Dictionary { + @package + int64_t _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithInt64s:(const int64_t [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary { + self = [self initWithInt64s:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithInt64s:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolInt64Dictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolInt64Dictionary class]]) { + return NO; + } + GPBBoolInt64Dictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %lld", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %lld", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getInt64:(int64_t *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueInt64; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%lld", _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%lld", _values[1]]); + } +} + +- (void)enumerateKeysAndInt64sUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int64_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setInt64:(int64_t)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeInt64ForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Bool, BOOL) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Bool + +@implementation GPBBoolBoolDictionary { + @package + BOOL _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithBools:(const BOOL [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary { + self = [self initWithBools:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithBools:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolBoolDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolBoolDictionary class]]) { + return NO; + } + GPBBoolBoolDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %d", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %d", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getBool:(BOOL *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueBool; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", (_values[0] ? @"true" : @"false")); + } + if (_valueSet[1]) { + block(@"true", (_values[1] ? @"true" : @"false")); + } +} + +- (void)enumerateKeysAndBoolsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, BOOL value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setBool:(BOOL)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeBoolForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Float, float) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Float + +@implementation GPBBoolFloatDictionary { + @package + float _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithFloats:(const float [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary { + self = [self initWithFloats:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithFloats:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolFloatDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolFloatDictionary class]]) { + return NO; + } + GPBBoolFloatDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %f", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %f", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getFloat:(float *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueFloat; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[1]]); + } +} + +- (void)enumerateKeysAndFloatsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, float value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setFloat:(float)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeFloatForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Double, double) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Double + +@implementation GPBBoolDoubleDictionary { + @package + double _values[2]; + BOOL _valueSet[2]; +} + +- (instancetype)init { + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithDoubles:(const double [])values + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = values[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary { + self = [self initWithDoubles:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithDoubles:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolDoubleDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolDoubleDictionary class]]) { + return NO; + } + GPBBoolDoubleDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %lf", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %lf", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getDouble:(double *)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + *value = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueDouble; + _valueSet[idx] = YES; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[0]]); + } + if (_valueSet[1]) { + block(@"true", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[1]]); + } +} + +- (void)enumerateKeysAndDoublesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, double value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setDouble:(double)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeDoubleForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(Object, id) +// This block of code is generated, do not edit it directly. + +#pragma mark - Bool -> Object + +@implementation GPBBoolObjectDictionary { + @package + id _values[2]; +} + +- (instancetype)init { + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + int idx = keys[i] ? 1 : 0; + [_values[idx] release]; + _values[idx] = (id)[objects[i] retain]; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary { + self = [self initWithObjects:NULL forKeys:NULL count:0]; + if (self) { + if (dictionary) { + _values[0] = [dictionary->_values[0] retain]; + _values[1] = [dictionary->_values[1] retain]; + } + } + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + #pragma unused(numItems) + return [self initWithObjects:NULL forKeys:NULL count:0]; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_values[0] release]; + [_values[1] release]; + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolObjectDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolObjectDictionary class]]) { + return NO; + } + GPBBoolObjectDictionary *otherDictionary = other; + if (((_values[0] != nil) != (otherDictionary->_values[0] != nil)) || + ((_values[1] != nil) != (otherDictionary->_values[1] != nil))) { + return NO; + } + if (((_values[0] != nil) && (![_values[0] isEqual:otherDictionary->_values[0]])) || + ((_values[1] != nil) && (![_values[1] isEqual:otherDictionary->_values[1]]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if ((_values[0] != nil)) { + [result appendFormat:@"NO: %@", _values[0]]; + } + if ((_values[1] != nil)) { + [result appendFormat:@"YES: %@", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0); +} + +- (id)objectForKey:(BOOL)key { + return _values[key ? 1 : 0]; +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + [_values[idx] release]; + _values[idx] = [value->valueString retain]; +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_values[0] != nil) { + block(@"false", _values[0]); + } + if ((_values[1] != nil)) { + block(@"true", _values[1]); + } +} + +- (void)enumerateKeysAndObjectsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, id object, BOOL *stop))block { + BOOL stop = NO; + if (_values[0] != nil) { + block(NO, _values[0], &stop); + } + if (!stop && (_values[1] != nil)) { + block(YES, _values[1], &stop); + } +} + +- (BOOL)isInitialized { + if (_values[0] && ![_values[0] isInitialized]) { + return NO; + } + if (_values[1] && ![_values[1] isInitialized]) { + return NO; + } + return YES; +} + +- (instancetype)deepCopyWithZone:(NSZone *)zone { + GPBBoolObjectDictionary *newDict = + [[GPBBoolObjectDictionary alloc] init]; + for (int i = 0; i < 2; ++i) { + if (_values[i] != nil) { + newDict->_values[i] = [_values[i] copyWithZone:zone]; + } + } + return newDict; +} + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_values[i] != nil) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_values[i] != nil) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_values[i] != nil) { + [_values[i] release]; + _values[i] = [otherDictionary->_values[i] retain]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setObject:(id)object forKey:(BOOL)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } + int idx = (key ? 1 : 0); + [_values[idx] release]; + _values[idx] = [object retain]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(BOOL)aKey { + int idx = (aKey ? 1 : 0); + [_values[idx] release]; + _values[idx] = nil; +} + +- (void)removeAll { + for (int i = 0; i < 2; ++i) { + [_values[i] release]; + _values[i] = nil; + } +} + +@end + +//%PDDM-EXPAND-END (8 expansions) + +#pragma mark - Bool -> Enum + +@implementation GPBBoolEnumDictionary { + @package + GPBEnumValidationFunc _validationFunc; + int32_t _values[2]; + BOOL _valueSet[2]; +} + +@synthesize validationFunc = _validationFunc; + +- (instancetype)init { + return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func { + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + rawValues:(const int32_t [])rawValues + forKeys:(const BOOL [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); + for (NSUInteger i = 0; i < count; ++i) { + int idx = keys[i] ? 1 : 0; + _values[idx] = rawValues[i]; + _valueSet[idx] = YES; + } + } + return self; +} + +- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary { + self = [self initWithValidationFunction:dictionary.validationFunc + rawValues:NULL + forKeys:NULL + count:0]; + if (self) { + if (dictionary) { + for (int i = 0; i < 2; ++i) { + if (dictionary->_valueSet[i]) { + _values[i] = dictionary->_values[i]; + _valueSet[i] = YES; + } + } + } + } + return self; +} + +- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func + capacity:(NSUInteger)numItems { +#pragma unused(numItems) + return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; +} + +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[GPBBoolEnumDictionary allocWithZone:zone] initWithDictionary:self]; +} + +- (BOOL)isEqual:(id)other { + if (self == other) { + return YES; + } + if (![other isKindOfClass:[GPBBoolEnumDictionary class]]) { + return NO; + } + GPBBoolEnumDictionary *otherDictionary = other; + if ((_valueSet[0] != otherDictionary->_valueSet[0]) || + (_valueSet[1] != otherDictionary->_valueSet[1])) { + return NO; + } + if ((_valueSet[0] && (_values[0] != otherDictionary->_values[0])) || + (_valueSet[1] && (_values[1] != otherDictionary->_values[1]))) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (NSString *)description { + NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self]; + if (_valueSet[0]) { + [result appendFormat:@"NO: %d", _values[0]]; + } + if (_valueSet[1]) { + [result appendFormat:@"YES: %d", _values[1]]; + } + [result appendString:@" }"]; + return result; +} + +- (NSUInteger)count { + return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0); +} + +- (BOOL)getEnum:(int32_t*)value forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (value) { + int32_t result = _values[idx]; + if (!_validationFunc(result)) { + result = kGPBUnrecognizedEnumeratorValue; + } + *value = result; + } + return YES; + } + return NO; +} + +- (BOOL)getRawValue:(int32_t*)rawValue forKey:(BOOL)key { + int idx = (key ? 1 : 0); + if (_valueSet[idx]) { + if (rawValue) { + *rawValue = _values[idx]; + } + return YES; + } + return NO; +} + +- (void)enumerateKeysAndRawValuesUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block { + BOOL stop = NO; + if (_valueSet[0]) { + block(NO, _values[0], &stop); + } + if (!stop && _valueSet[1]) { + block(YES, _values[1], &stop); + } +} + +- (void)enumerateKeysAndEnumsUsingBlock: + (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block { + BOOL stop = NO; + GPBEnumValidationFunc func = _validationFunc; + int32_t validatedValue; + if (_valueSet[0]) { + validatedValue = _values[0]; + if (!func(validatedValue)) { + validatedValue = kGPBUnrecognizedEnumeratorValue; + } + block(NO, validatedValue, &stop); + } + if (!stop && _valueSet[1]) { + validatedValue = _values[1]; + if (!func(validatedValue)) { + validatedValue = kGPBUnrecognizedEnumeratorValue; + } + block(YES, validatedValue, &stop); + } +} + +//%PDDM-EXPAND SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) +// This block of code is generated, do not edit it directly. + +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); + NSMutableData *data = [NSMutableData dataWithLength:msgSize]; + GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; + WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); + [outputStream release]; + return data; +} + +//%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) + +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSUInteger count = 0; + size_t result = 0; + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + ++count; + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; + } + } + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); + result += tagSize * count; + return result; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field { + GPBDataType valueDataType = GPBGetFieldDataType(field); + uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); + for (int i = 0; i < 2; ++i) { + if (_valueSet[i]) { + // Write the tag. + [outputStream writeInt32NoTag:tag]; + // Write the size of the message. + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); + [outputStream writeInt32NoTag:(int32_t)msgSize]; + // Write the fields. + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); + } + } +} + +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { + if (_valueSet[0]) { + block(@"false", @(_values[0])); + } + if (_valueSet[1]) { + block(@"true", @(_values[1])); + } +} + +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { + int idx = (key->valueBool ? 1 : 0); + _values[idx] = value->valueInt32; + _valueSet[idx] = YES; +} + +- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary { + if (otherDictionary) { + for (int i = 0; i < 2; ++i) { + if (otherDictionary->_valueSet[i]) { + _valueSet[i] = YES; + _values[i] = otherDictionary->_values[i]; + } + } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } + } +} + +- (void)setEnum:(int32_t)value forKey:(BOOL)key { + if (!_validationFunc(value)) { + [NSException raise:NSInvalidArgumentException + format:@"GPBBoolEnumDictionary: Attempt to set an unknown enum value (%d)", + value]; + } + int idx = (key ? 1 : 0); + _values[idx] = value; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key { + int idx = (key ? 1 : 0); + _values[idx] = rawValue; + _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeEnumForKey:(BOOL)aKey { + _valueSet[aKey ? 1 : 0] = NO; +} + +- (void)removeAll { + _valueSet[0] = NO; + _valueSet[1] = NO; +} + +@end + +#pragma mark - NSDictionary Subclass + +@implementation GPBAutocreatedDictionary { + NSMutableDictionary *_dictionary; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +#pragma mark Required NSDictionary overrides + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const id [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] initWithObjects:objects + forKeys:keys + count:count]; + } + return self; +} + +- (NSUInteger)count { + return [_dictionary count]; +} + +- (id)objectForKey:(id)aKey { + return [_dictionary objectForKey:aKey]; +} + +- (NSEnumerator *)keyEnumerator { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + return [_dictionary keyEnumerator]; +} + +#pragma mark Required NSMutableDictionary overrides + +// Only need to call GPBAutocreatedDictionaryModified() when adding things +// since we only autocreate empty dictionaries. + +- (void)setObject:(id)anObject forKey:(id)aKey { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + [_dictionary setObject:anObject forKey:aKey]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(id)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +#pragma mark Extra things hooked + +- (id)copyWithZone:(NSZone *)zone { + if (_dictionary == nil) { + return [[NSMutableDictionary allocWithZone:zone] init]; + } + return [_dictionary copyWithZone:zone]; +} + +- (id)mutableCopyWithZone:(NSZone *)zone { + if (_dictionary == nil) { + return [[NSMutableDictionary allocWithZone:zone] init]; + } + return [_dictionary mutableCopyWithZone:zone]; +} + +// Not really needed, but subscripting is likely common enough it doesn't hurt +// to ensure it goes directly to the real NSMutableDictionary. +- (id)objectForKeyedSubscript:(id)key { + return [_dictionary objectForKeyedSubscript:key]; +} + +// Not really needed, but subscripting is likely common enough it doesn't hurt +// to ensure it goes directly to the real NSMutableDictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + [_dictionary setObject:obj forKeyedSubscript:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)enumerateKeysAndObjectsUsingBlock:(void (NS_NOESCAPE ^)(id key, + id obj, + BOOL *stop))block { + [_dictionary enumerateKeysAndObjectsUsingBlock:block]; +} + +- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (NS_NOESCAPE ^)(id key, + id obj, + BOOL *stop))block { + [_dictionary enumerateKeysAndObjectsWithOptions:opts usingBlock:block]; +} + +@end + +#pragma clang diagnostic pop diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary_PackagePrivate.h new file mode 100644 index 0000000..7b921e8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBDictionary_PackagePrivate.h @@ -0,0 +1,488 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBDictionary.h" + +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionRegistry; +@class GPBFieldDescriptor; + +@protocol GPBDictionaryInternalsProtocol +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field; +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key; +- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@end + +//%PDDM-DEFINE DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(KEY_NAME) +//%DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Object, Object) +//%PDDM-DEFINE DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt32, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int32, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt64, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int64, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Bool, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Float, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Double, Basic) +//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Enum, Enum) + +//%PDDM-DEFINE DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, VALUE_NAME, HELPER) +//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary () { +//% @package +//% GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +//%} +//%EXTRA_DICTIONARY_PRIVATE_INTERFACES_##HELPER()@end +//% + +//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Basic() +// Empty +//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Object() +//%- (BOOL)isInitialized; +//%- (instancetype)deepCopyWithZone:(NSZone *)zone +//% __attribute__((ns_returns_retained)); +//% +//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum() +//%- (NSData *)serializedDataForUnknownValue:(int32_t)value +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType; +//% + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32) +// This block of code is generated, do not edit it directly. + +@interface GPBUInt32UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt32EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBUInt32ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32) +// This block of code is generated, do not edit it directly. + +@interface GPBInt32UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt32EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBInt32ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64) +// This block of code is generated, do not edit it directly. + +@interface GPBUInt64UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBUInt64EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBUInt64ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64) +// This block of code is generated, do not edit it directly. + +@interface GPBInt64UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBInt64EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBInt64ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool) +// This block of code is generated, do not edit it directly. + +@interface GPBBoolUInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolUInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolBoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolFloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolDoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBBoolEnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +@interface GPBBoolObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (BOOL)isInitialized; +- (instancetype)deepCopyWithZone:(NSZone *)zone + __attribute__((ns_returns_retained)); +@end + +//%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String) +// This block of code is generated, do not edit it directly. + +@interface GPBStringUInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringUInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringBoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringFloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringDoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +@interface GPBStringEnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +- (NSData *)serializedDataForUnknownValue:(int32_t)value + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; +@end + +//%PDDM-EXPAND-END (6 expansions) + +#pragma mark - NSDictionary Subclass + +@interface GPBAutocreatedDictionary : NSMutableDictionary { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Helpers + +CF_EXTERN_C_BEGIN + +// Helper to compute size when an NSDictionary is used for the map instead +// of a custom type. +size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, + GPBFieldDescriptor *field); + +// Helper to write out when an NSDictionary is used for the map instead +// of a custom type. +void GPBDictionaryWriteToStreamInternalHelper( + GPBCodedOutputStream *outputStream, NSDictionary *dict, + GPBFieldDescriptor *field); + +// Helper to check message initialization when an NSDictionary is used for +// the map instead of a custom type. +BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, + GPBFieldDescriptor *field); + +// Helper to read a map instead. +void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream, + GPBExtensionRegistry *registry, + GPBFieldDescriptor *field, + GPBMessage *parentMessage); + +CF_EXTERN_C_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionInternals.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionInternals.h new file mode 100644 index 0000000..2b980ae --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionInternals.h @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBDescriptor.h" + +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionRegistry; + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message); + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value); + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionInternals.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionInternals.m new file mode 100644 index 0000000..290c82a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionInternals.m @@ -0,0 +1,391 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBExtensionInternals.h" + +#import + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) + __attribute__((ns_returns_retained)); + +GPB_INLINE size_t DataTypeSize(GPBDataType dataType) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (dataType) { + case GPBDataTypeBool: + return 1; + case GPBDataTypeFixed32: + case GPBDataTypeSFixed32: + case GPBDataTypeFloat: + return 4; + case GPBDataTypeFixed64: + case GPBDataTypeSFixed64: + case GPBDataTypeDouble: + return 8; + default: + return 0; + } +#pragma clang diagnostic pop +} + +static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag(object); + switch (dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + FIELD_CASE2(Group) + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static size_t ComputeSerializedSizeIncludingTagOfObject( + GPBExtensionDescription *description, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, \ + [(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, object); + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(description)) { + return GPBComputeMessageSetExtensionSize(description->fieldNumber, + object); + } else { + return GPBComputeMessageSize(description->fieldNumber, object); + } + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static size_t ComputeSerializedSizeIncludingTagOfArray( + GPBExtensionDescription *description, NSArray *values) { + if (GPBExtensionIsPacked(description)) { + size_t size = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + size = values.count * typeSize; + } else { + for (id value in values) { + size += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + return size + GPBComputeTagSize(description->fieldNumber) + + GPBComputeRawVarint32SizeForInteger(size); + } else { + size_t size = 0; + for (id value in values) { + size += ComputeSerializedSizeIncludingTagOfObject(description, value); + } + return size; + } +} + +static void WriteObjectIncludingTagToCodedOutputStream( + id object, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber \ + value:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber value:object]; \ + return; + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(description)) { + [output writeMessageSetExtension:description->fieldNumber value:object]; + } else { + [output writeMessage:description->fieldNumber value:object]; + } + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteObjectNoTagToCodedOutputStream( + id object, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:object]; \ + return; + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + case GPBDataTypeGroup: + [output writeGroupNoTag:description->fieldNumber value:object]; + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteArrayIncludingTagsToCodedOutputStream( + NSArray *values, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { + if (GPBExtensionIsPacked(description)) { + [output writeTag:description->fieldNumber + format:GPBWireFormatLengthDelimited]; + size_t dataSize = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + dataSize = values.count * typeSize; + } else { + for (id value in values) { + dataSize += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + [output writeRawVarintSizeTAs32:dataSize]; + for (id value in values) { + WriteObjectNoTagToCodedOutputStream(value, description, output); + } + } else { + for (id value in values) { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } + } +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + if (isPackedOnStream) { + NSCAssert(GPBExtensionIsRepeated(description), + @"How was it packed if it isn't repeated?"); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + nil); + [message addExtension:extension value:value]; + [value release]; + } + GPBCodedInputStreamPopLimit(state, limit); + } else { + id existingValue = nil; + BOOL isRepeated = GPBExtensionIsRepeated(description); + if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) { + existingValue = [message getExistingExtension:extension]; + } + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + existingValue); + if (isRepeated) { + [message addExtension:extension value:value]; + } else { + [message setExtension:extension value:value]; + } + [value release]; + } +} + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + WriteArrayIncludingTagsToCodedOutputStream(value, description, output); + } else { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } +} + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + return ComputeSerializedSizeIncludingTagOfArray(description, value); + } else { + return ComputeSerializedSizeIncludingTagOfObject(description, value); + } +} + +// Note that this returns a retained value intentionally. +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + switch (description->dataType) { + case GPBDataTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)]; + case GPBDataTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)]; + case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)]; + case GPBDataTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)]; + case GPBDataTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)]; + case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)]; + case GPBDataTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)]; + case GPBDataTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)]; + case GPBDataTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)]; + case GPBDataTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)]; + case GPBDataTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)]; + case GPBDataTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)]; + case GPBDataTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)]; + case GPBDataTypeBytes: return GPBCodedInputStreamReadRetainedBytes(state); + case GPBDataTypeString: return GPBCodedInputStreamReadRetainedString(state); + case GPBDataTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)]; + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + GPBMessage *message; + if (existingValue) { + message = [existingValue retain]; + } else { + GPBDescriptor *decriptor = [extension.msgClass descriptor]; + message = [[decriptor.messageClass alloc] init]; + } + + if (description->dataType == GPBDataTypeGroup) { + [input readGroup:description->fieldNumber + message:message + extensionRegistry:extensionRegistry]; + } else { + // description->dataType == GPBDataTypeMessage + if (GPBExtensionIsWireFormat(description)) { + // For MessageSet fields the message length will have already been + // read. + [message mergeFromCodedInputStream:input + extensionRegistry:extensionRegistry]; + } else { + [input readMessage:message extensionRegistry:extensionRegistry]; + } + } + + return message; + } + } + + return nil; +} + +#pragma clang diagnostic pop diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.h new file mode 100644 index 0000000..d79632d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.h @@ -0,0 +1,87 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBDescriptor; +@class GPBExtensionDescriptor; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A table of known extensions, searchable by name or field number. When + * parsing a protocol message that might have extensions, you must provide a + * GPBExtensionRegistry in which you have registered any extensions that you + * want to be able to parse. Otherwise, those extensions will just be treated + * like unknown fields. + * + * The *Root classes provide `+extensionRegistry` for the extensions defined + * in a given file *and* all files it imports. You can also create a + * GPBExtensionRegistry, and merge those registries to handle parsing + * extensions defined from non overlapping files. + * + * ``` + * GPBExtensionRegistry *registry = [[MyProtoFileRoot extensionRegistry] copy]; + * [registry addExtension:[OtherMessage neededExtension]]; // Not in MyProtoFile + * NSError *parseError; + * MyMessage *msg = [MyMessage parseData:data extensionRegistry:registry error:&parseError]; + * ``` + **/ +@interface GPBExtensionRegistry : NSObject + +/** + * Adds the given GPBExtensionDescriptor to this registry. + * + * @param extension The extension description to add. + **/ +- (void)addExtension:(GPBExtensionDescriptor *)extension; + +/** + * Adds all the extensions from another registry to this registry. + * + * @param registry The registry to merge into this registry. + **/ +- (void)addExtensions:(GPBExtensionRegistry *)registry; + +/** + * Looks for the extension registered for the given field number on a given + * GPBDescriptor. + * + * @param descriptor The descriptor to look for a registered extension on. + * @param fieldNumber The field number of the extension to look for. + * + * @return The registered GPBExtensionDescriptor or nil if none was found. + **/ +- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.m new file mode 100644 index 0000000..b056a52 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBExtensionRegistry.m @@ -0,0 +1,130 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBExtensionRegistry.h" + +#import "GPBBootstrap.h" +#import "GPBDescriptor.h" + +@implementation GPBExtensionRegistry { + NSMutableDictionary *mutableClassMap_; +} + +- (instancetype)init { + if ((self = [super init])) { + mutableClassMap_ = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)dealloc { + [mutableClassMap_ release]; + [super dealloc]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (instancetype)copyWithZone:(NSZone *)zone { + GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; + [result addExtensions:self]; + return result; +} + +- (void)addExtension:(GPBExtensionDescriptor *)extension { + if (extension == nil) { + return; + } + + Class containingMessageClass = extension.containingMessageClass; + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + [mutableClassMap_ objectForKey:containingMessageClass]; + if (extensionMap == nil) { + // Use a custom dictionary here because the keys are numbers and conversion + // back and forth from NSNumber isn't worth the cost. + extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, + &kCFTypeDictionaryValueCallBacks); + [mutableClassMap_ setObject:(id)extensionMap + forKey:(id)containingMessageClass]; + CFRelease(extensionMap); + } + + ssize_t key = extension.fieldNumber; + CFDictionarySetValue(extensionMap, (const void *)key, extension); +} + +- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber { + Class messageClass = descriptor.messageClass; + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + [mutableClassMap_ objectForKey:messageClass]; + ssize_t key = fieldNumber; + GPBExtensionDescriptor *result = + (extensionMap + ? CFDictionaryGetValue(extensionMap, (const void *)key) + : nil); + return result; +} + +static void CopyKeyValue(const void *key, const void *value, void *context) { + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)context; + CFDictionarySetValue(extensionMap, key, value); +} + +- (void)addExtensions:(GPBExtensionRegistry *)registry { + if (registry == nil) { + // In the case where there are no extensions just ignore. + return; + } + NSMutableDictionary *otherClassMap = registry->mutableClassMap_; + [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) { +#pragma unused(stop) + Class containingMessageClass = key; + CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; + + CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + [mutableClassMap_ objectForKey:containingMessageClass]; + if (extensionMap == nil) { + extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap); + [mutableClassMap_ setObject:(id)extensionMap + forKey:(id)containingMessageClass]; + CFRelease(extensionMap); + } else { + CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); + } + }]; +} + +#pragma clang diagnostic pop + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage.h new file mode 100644 index 0000000..276740d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage.h @@ -0,0 +1,470 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBBootstrap.h" + +@class GPBDescriptor; +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionDescriptor; +@class GPBExtensionRegistry; +@class GPBFieldDescriptor; +@class GPBUnknownFieldSet; + +NS_ASSUME_NONNULL_BEGIN + +CF_EXTERN_C_BEGIN + +/** NSError domain used for errors. */ +extern NSString *const GPBMessageErrorDomain; + +/** Error codes for NSErrors originated in GPBMessage. */ +typedef NS_ENUM(NSInteger, GPBMessageErrorCode) { + /** Uncategorized error. */ + GPBMessageErrorCodeOther = -100, + /** Message couldn't be serialized because it is missing required fields. */ + GPBMessageErrorCodeMissingRequiredField = -101, +}; + +/** + * Key under which the GPBMessage error's reason is stored inside the userInfo + * dictionary. + **/ +extern NSString *const GPBErrorReasonKey; + +CF_EXTERN_C_END + +/** + * Base class that each generated message subclasses from. + * + * @note @c NSCopying support is a "deep copy", in that all sub objects are + * copied. Just like you wouldn't want a UIView/NSView trying to + * exist in two places, you don't want a sub message to be a property + * property of two other messages. + * + * @note While the class support NSSecureCoding, if the message has any + * extensions, they will end up reloaded in @c unknownFields as there is + * no way for the @c NSCoding plumbing to pass through a + * @c GPBExtensionRegistry. To support extensions, instead of passing the + * calls off to the Message, simple store the result of @c data, and then + * when loading, fetch the data and use + * @c +parseFromData:extensionRegistry:error: to provide an extension + * registry. + **/ +@interface GPBMessage : NSObject + +// If you add an instance method/property to this class that may conflict with +// fields declared in protos, you need to update objective_helpers.cc. The main +// cases are methods that take no arguments, or setFoo:/hasFoo: type methods. + +/** + * The set of unknown fields for this message. + * + * Only messages from proto files declared with "proto2" syntax support unknown + * fields. For "proto3" syntax, any unknown fields found while parsing are + * dropped. + **/ +@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields; + +/** + * Whether the message, along with all submessages, have the required fields + * set. This is only applicable for files declared with "proto2" syntax, as + * there are no required fields for "proto3" syntax. + **/ +@property(nonatomic, readonly, getter=isInitialized) BOOL initialized; + +/** + * @return An autoreleased message with the default values set. + **/ ++ (instancetype)message; + +/** + * Creates a new instance by parsing the provided data. This method should be + * sent to the generated message class that the data should be interpreted as. + * If there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param errorPtr An optional error pointer to fill in with a failure reason if + * the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr; + +/** + * Creates a new instance by parsing the data. This method should be sent to + * the generated message class that the data should be interpreted as. If + * there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseFromData:(NSData *)data + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Creates a new instance by parsing the data from the given input stream. This + * method should be sent to the generated message class that the data should + * be interpreted as. If there is an error the method returns nil and the error + * is returned in errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param input The stream to read data from. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Creates a new instance by parsing the data from the given input stream. This + * method should be sent to the generated message class that the data should + * be interpreted as. If there is an error the method returns nil and the error + * is returned in errorPtr (when provided). + * + * @note Unlike the parseFrom... methods, this never checks to see if all of + * the required fields are set. So this method can be used to reload + * messages that may not be complete. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param input The stream to read data from. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return A new instance of the generated class. + **/ ++ (nullable instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Initializes an instance by parsing the data. This method should be sent to + * the generated message class that the data should be interpreted as. If + * there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param errorPtr An optional error pointer to fill in with a failure reason if + * the data can not be parsed. + * + * @return An initialized instance of the generated class. + **/ +- (nullable instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr; + +/** + * Initializes an instance by parsing the data. This method should be sent to + * the generated message class that the data should be interpreted as. If + * there is an error the method returns nil and the error is returned in + * errorPtr (when provided). + * + * @note In DEBUG builds, the parsed message is checked to be sure all required + * fields were provided, and the parse will fail if some are missing. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param data The data to parse. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return An initialized instance of the generated class. + **/ +- (nullable instancetype)initWithData:(NSData *)data + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Initializes an instance by parsing the data from the given input stream. This + * method should be sent to the generated message class that the data should + * be interpreted as. If there is an error the method returns nil and the error + * is returned in errorPtr (when provided). + * + * @note Unlike the parseFrom... methods, this never checks to see if all of + * the required fields are set. So this method can be used to reload + * messages that may not be complete. + * + * @note The errors returned are likely coming from the domain and codes listed + * at the top of this file and GPBCodedInputStream.h. + * + * @param input The stream to read data from. + * @param extensionRegistry The extension registry to use to look up extensions. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. + * + * @return An initialized instance of the generated class. + **/ +- (nullable instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (nullable GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +/** + * Parses the given data as this message's class, and merges those values into + * this message. + * + * @param data The binary representation of the message to merge. + * @param extensionRegistry The extension registry to use to look up extensions. + * + * @exception GPBCodedInputStreamException Exception thrown when parsing was + * unsuccessful. + **/ +- (void)mergeFromData:(NSData *)data + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry; + +/** + * Merges the fields from another message (of the same type) into this + * message. + * + * @param other Message to merge into this message. + **/ +- (void)mergeFrom:(GPBMessage *)other; + +/** + * Writes out the message to the given coded output stream. + * + * @param output The coded output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + * + **/ +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output; + +/** + * Writes out the message to the given output stream. + * + * @param output The output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + **/ +- (void)writeToOutputStream:(NSOutputStream *)output; + +/** + * Writes out a varint for the message size followed by the the message to + * the given output stream. + * + * @param output The coded output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + **/ +- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output; + +/** + * Writes out a varint for the message size followed by the the message to + * the given output stream. + * + * @param output The output stream into which to write the message. + * + * @note This can raise the GPBCodedOutputStreamException_* exceptions. + **/ +- (void)writeDelimitedToOutputStream:(NSOutputStream *)output; + +/** + * Serializes the message to an NSData. + * + * If there is an error while generating the data, nil is returned. + * + * @note This value is not cached, so if you are using it repeatedly, cache + * it yourself. + * + * @note In DEBUG ONLY, the message is also checked for all required field, + * if one is missing, nil will be returned. + * + * @return The binary representation of the message. + **/ +- (nullable NSData *)data; + +/** + * Serializes a varint with the message size followed by the message data, + * returning that as an NSData. + * + * @note This value is not cached, so if you are using it repeatedly, it is + * recommended to keep a local copy. + * + * @return The binary representation of the size along with the message. + **/ +- (NSData *)delimitedData; + +/** + * Calculates the size of the object if it were serialized. + * + * This is not a cached value. If you are following a pattern like this: + * + * ``` + * size_t size = [aMsg serializedSize]; + * NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; + * [foo writeSize:size]; + * [foo appendData:[aMsg data]]; + * ``` + * + * you would be better doing: + * + * ``` + * NSData *data = [aMsg data]; + * NSUInteger size = [aMsg length]; + * NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; + * [foo writeSize:size]; + * [foo appendData:data]; + * ``` + * + * @return The size of the message in it's binary representation. + **/ +- (size_t)serializedSize; + +/** + * @return The descriptor for the message class. + **/ ++ (GPBDescriptor *)descriptor; + +/** + * Return the descriptor for the message. + **/ +- (GPBDescriptor *)descriptor; + +/** + * @return An array with the extension descriptors that are currently set on the + * message. + **/ +- (NSArray *)extensionsCurrentlySet; + +/** + * Checks whether there is an extension set on the message which matches the + * given extension descriptor. + * + * @param extension Extension descriptor to check if it's set on the message. + * + * @return Whether the extension is currently set on the message. + **/ +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension; + +/* + * Fetches the given extension's value for this message. + * + * Extensions use boxed values (NSNumbers) for PODs and NSMutableArrays for + * repeated fields. If the extension is a Message one will be auto created for + * you and returned similar to fields. + * + * @param extension The extension descriptor of the extension to fetch. + * + * @return The extension matching the given descriptor, or nil if none found. + **/ +- (nullable id)getExtension:(GPBExtensionDescriptor *)extension; + +/** + * Sets the given extension's value for this message. This only applies for + * single field extensions (i.e. - not repeated fields). + * + * Extensions use boxed values (NSNumbers). + * + * @param extension The extension descriptor under which to set the value. + * @param value The value to be set as the extension. + **/ +- (void)setExtension:(GPBExtensionDescriptor *)extension + value:(nullable id)value; + +/** + * Adds the given value to the extension for this message. This only applies + * to repeated field extensions. If the field is a repeated POD type, the value + * should be an NSNumber. + * + * @param extension The extension descriptor under which to add the value. + * @param value The value to be added to the repeated extension. + **/ +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value; + +/** + * Replaces the value at the given index with the given value for the extension + * on this message. This only applies to repeated field extensions. If the field + * is a repeated POD type, the value is should be an NSNumber. + * + * @param extension The extension descriptor under which to replace the value. + * @param index The index of the extension to be replaced. + * @param value The value to be replaced in the repeated extension. + **/ +- (void)setExtension:(GPBExtensionDescriptor *)extension + index:(NSUInteger)index + value:(id)value; + +/** + * Clears the given extension for this message. + * + * @param extension The extension descriptor to be cleared from this message. + **/ +- (void)clearExtension:(GPBExtensionDescriptor *)extension; + +/** + * Resets all of the fields of this message to their default values. + **/ +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage.m new file mode 100644 index 0000000..3d5eccd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage.m @@ -0,0 +1,3348 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBMessage_PackagePrivate.h" + +#import +#import +#import + +#import "GPBArray_PackagePrivate.h" +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary_PackagePrivate.h" +#import "GPBExtensionInternals.h" +#import "GPBExtensionRegistry.h" +#import "GPBRootObject_PackagePrivate.h" +#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +NSString *const GPBMessageErrorDomain = + GPBNSStringifySymbol(GPBMessageErrorDomain); + +NSString *const GPBErrorReasonKey = @"Reason"; + +static NSString *const kGPBDataCoderKey = @"GPBData"; + +// +// PLEASE REMEMBER: +// +// This is the base class for *all* messages generated, so any selector defined, +// *public* or *private* could end up colliding with a proto message field. So +// avoid using selectors that could match a property, use C functions to hide +// them, etc. +// + +@interface GPBMessage () { + @package + GPBUnknownFieldSet *unknownFields_; + NSMutableDictionary *extensionMap_; + NSMutableDictionary *autocreatedExtensionMap_; + + // If the object was autocreated, we remember the creator so that if we get + // mutated, we can inform the creator to make our field visible. + GPBMessage *autocreator_; + GPBFieldDescriptor *autocreatorField_; + GPBExtensionDescriptor *autocreatorExtension_; + + // A lock to provide mutual exclusion from internal data that can be modified + // by *read* operations such as getters (autocreation of message fields and + // message extensions, not setting of values). Used to guarantee thread safety + // for concurrent reads on the message. + // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have + // pointed out that they are vulnerable to live locking on iOS in cases of + // priority inversion: + // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ + // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html + // Use of readOnlySemaphore_ must be prefaced by a call to + // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows + // readOnlySemaphore_ to be only created when actually needed. + _Atomic(dispatch_semaphore_t) readOnlySemaphore_; +} +@end + +static id CreateArrayForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) + __attribute__((ns_returns_retained)); +static id GetOrCreateArrayIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax); +static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); +static id CreateMapForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) + __attribute__((ns_returns_retained)); +static id GetOrCreateMapIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax); +static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); +static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, + NSZone *zone) + __attribute__((ns_returns_retained)); + +#ifdef DEBUG +static NSError *MessageError(NSInteger code, NSDictionary *userInfo) { + return [NSError errorWithDomain:GPBMessageErrorDomain + code:code + userInfo:userInfo]; +} +#endif + +static NSError *ErrorFromException(NSException *exception) { + NSError *error = nil; + + if ([exception.name isEqual:GPBCodedInputStreamException]) { + NSDictionary *exceptionInfo = exception.userInfo; + error = exceptionInfo[GPBCodedInputStreamUnderlyingErrorKey]; + } + + if (!error) { + NSString *reason = exception.reason; + NSDictionary *userInfo = nil; + if ([reason length]) { + userInfo = @{ GPBErrorReasonKey : reason }; + } + + error = [NSError errorWithDomain:GPBMessageErrorDomain + code:GPBMessageErrorCodeOther + userInfo:userInfo]; + } + return error; +} + +static void CheckExtension(GPBMessage *self, + GPBExtensionDescriptor *extension) { + if (![self isKindOfClass:extension.containingMessageClass]) { + [NSException + raise:NSInvalidArgumentException + format:@"Extension %@ used on wrong class (%@ instead of %@)", + extension.singletonName, + [self class], extension.containingMessageClass]; + } +} + +static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, + NSZone *zone) { + if (extensionMap.count == 0) { + return nil; + } + NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone] + initWithCapacity:extensionMap.count]; + + for (GPBExtensionDescriptor *extension in extensionMap) { + id value = [extensionMap objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); + + if (extension.repeated) { + if (isMessageExtension) { + NSMutableArray *list = + [[NSMutableArray alloc] initWithCapacity:[value count]]; + for (GPBMessage *listValue in value) { + GPBMessage *copiedValue = [listValue copyWithZone:zone]; + [list addObject:copiedValue]; + [copiedValue release]; + } + [result setObject:list forKey:extension]; + [list release]; + } else { + NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; + [result setObject:copiedValue forKey:extension]; + [copiedValue release]; + } + } else { + if (isMessageExtension) { + GPBMessage *copiedValue = [value copyWithZone:zone]; + [result setObject:copiedValue forKey:extension]; + [copiedValue release]; + } else { + [result setObject:value forKey:extension]; + } + } + } + + return result; +} + +static id CreateArrayForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) { + id result; + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { + case GPBDataTypeBool: + result = [[GPBBoolArray alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBUInt32Array alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBInt32Array alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBUInt64Array alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBInt64Array alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBFloatArray alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBDoubleArray alloc] init]; + break; + + case GPBDataTypeEnum: + result = [[GPBEnumArray alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + case GPBDataTypeString: + if (autocreator) { + result = [[GPBAutocreatedArray alloc] init]; + } else { + result = [[NSMutableArray alloc] init]; + } + break; + } + + if (autocreator) { + if (GPBDataTypeIsObject(fieldDataType)) { + GPBAutocreatedArray *autoArray = result; + autoArray->_autocreator = autocreator; + } else { + GPBInt32Array *gpbArray = result; + gpbArray->_autocreator = autocreator; + } + } + + return result; +} + +static id CreateMapForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) { + id result; + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + switch (keyDataType) { + case GPBDataTypeBool: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBBoolBoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBBoolUInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBBoolInt32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBBoolUInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBBoolInt64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBBoolFloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBBoolDoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBBoolEnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBBoolObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBUInt32BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBUInt32UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBUInt32Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBUInt32UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBUInt32Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBUInt32FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBUInt32DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBUInt32EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBUInt32ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBInt32BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBInt32UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBInt32Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBInt32UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBInt32Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBInt32FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBInt32DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBInt32EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBInt32ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBUInt64BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBUInt64UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBUInt64Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBUInt64UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBUInt64Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBUInt64FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBUInt64DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBUInt64EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBUInt64ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBInt64BoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBInt64UInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBInt64Int32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBInt64UInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBInt64Int64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBInt64FloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBInt64DoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBInt64EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + result = [[GPBInt64ObjectDictionary alloc] init]; + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBDataTypeString: + switch (valueDataType) { + case GPBDataTypeBool: + result = [[GPBStringBoolDictionary alloc] init]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + result = [[GPBStringUInt32Dictionary alloc] init]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + result = [[GPBStringInt32Dictionary alloc] init]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + result = [[GPBStringUInt64Dictionary alloc] init]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + result = [[GPBStringInt64Dictionary alloc] init]; + break; + case GPBDataTypeFloat: + result = [[GPBStringFloatDictionary alloc] init]; + break; + case GPBDataTypeDouble: + result = [[GPBStringDoubleDictionary alloc] init]; + break; + case GPBDataTypeEnum: + result = [[GPBStringEnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: + if (autocreator) { + result = [[GPBAutocreatedDictionary alloc] init]; + } else { + result = [[NSMutableDictionary alloc] init]; + } + break; + case GPBDataTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeEnum: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + + if (autocreator) { + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + GPBAutocreatedDictionary *autoDict = result; + autoDict->_autocreator = autocreator; + } else { + GPBInt32Int32Dictionary *gpbDict = result; + gpbDict->_autocreator = autocreator; + } + } + + return result; +} + +#if !defined(__clang_analyzer__) +// These functions are blocked from the analyzer because the analyzer sees the +// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map, +// so use of the array/map after the call returns is flagged as a use after +// free. +// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain +// count be holding onto the object (it is transfering it), the object is +// still valid after returning from the call. The other way to avoid this +// would be to add a -retain/-autorelease, but that would force every +// repeated/map field parsed into the autorelease pool which is both a memory +// and performance hit. + +static id GetOrCreateArrayIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax) { + id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!array) { + // No lock needed, this is called from places expecting to mutate + // so no threading protection is needed. + array = CreateArrayForField(field, nil); + GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax); + } + return array; +} + +// This is like GPBGetObjectIvarWithField(), but for arrays, it should +// only be used to wire the method into the class. +static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!array) { + // Check again after getting the lock. + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); + array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!array) { + array = CreateArrayForField(field, self); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); + } + dispatch_semaphore_signal(self->readOnlySemaphore_); + } + return array; +} + +static id GetOrCreateMapIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax) { + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + // No lock needed, this is called from places expecting to mutate + // so no threading protection is needed. + dict = CreateMapForField(field, nil); + GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); + } + return dict; +} + +// This is like GPBGetObjectIvarWithField(), but for maps, it should +// only be used to wire the method into the class. +static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + // Check again after getting the lock. + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); + dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + dict = CreateMapForField(field, self); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); + } + dispatch_semaphore_signal(self->readOnlySemaphore_); + } + return dict; +} + +#endif // !defined(__clang_analyzer__) + +GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, + GPBMessage *autocreator, + GPBFieldDescriptor *field) { + GPBMessage *message = [[msgClass alloc] init]; + message->autocreator_ = autocreator; + message->autocreatorField_ = [field retain]; + return message; +} + +static GPBMessage *CreateMessageWithAutocreatorForExtension( + Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension) + __attribute__((ns_returns_retained)); + +static GPBMessage *CreateMessageWithAutocreatorForExtension( + Class msgClass, GPBMessage *autocreator, + GPBExtensionDescriptor *extension) { + GPBMessage *message = [[msgClass alloc] init]; + message->autocreator_ = autocreator; + message->autocreatorExtension_ = [extension retain]; + return message; +} + +BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) { + return (message->autocreator_ == parent); +} + +void GPBBecomeVisibleToAutocreator(GPBMessage *self) { + // Message objects that are implicitly created by accessing a message field + // are initially not visible via the hasX selector. This method makes them + // visible. + if (self->autocreator_) { + // This will recursively make all parent messages visible until it reaches a + // super-creator that's visible. + if (self->autocreatorField_) { + GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax; + GPBSetObjectIvarWithFieldInternal(self->autocreator_, + self->autocreatorField_, self, syntax); + } else { + [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; + } + } +} + +void GPBAutocreatedArrayModified(GPBMessage *self, id array) { + // When one of our autocreated arrays adds elements, make it visible. + GPBDescriptor *descriptor = [[self class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.fieldType == GPBFieldTypeRepeated) { + id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (curArray == array) { + if (GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedArray *autoArray = array; + autoArray->_autocreator = nil; + } else { + GPBInt32Array *gpbArray = array; + gpbArray->_autocreator = nil; + } + GPBBecomeVisibleToAutocreator(self); + return; + } + } + } + NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self); +} + +void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { + // When one of our autocreated dicts adds elements, make it visible. + GPBDescriptor *descriptor = [[self class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.fieldType == GPBFieldTypeMap) { + id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (curDict == dictionary) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedDictionary *autoDict = dictionary; + autoDict->_autocreator = nil; + } else { + GPBInt32Int32Dictionary *gpbDict = dictionary; + gpbDict->_autocreator = nil; + } + GPBBecomeVisibleToAutocreator(self); + return; + } + } + } + NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self); +} + +void GPBClearMessageAutocreator(GPBMessage *self) { + if ((self == nil) || !self->autocreator_) { + return; + } + +#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) + // Either the autocreator must have its "has" flag set to YES, or it must be + // NO and not equal to ourselves. + BOOL autocreatorHas = + (self->autocreatorField_ + ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_) + : [self->autocreator_ hasExtension:self->autocreatorExtension_]); + GPBMessage *autocreatorFieldValue = + (self->autocreatorField_ + ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, + self->autocreatorField_) + : [self->autocreator_->autocreatedExtensionMap_ + objectForKey:self->autocreatorExtension_]); + NSCAssert(autocreatorHas || autocreatorFieldValue != self, + @"Cannot clear autocreator because it still refers to self, self: %@.", + self); + +#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) + + self->autocreator_ = nil; + [self->autocreatorField_ release]; + self->autocreatorField_ = nil; + [self->autocreatorExtension_ release]; + self->autocreatorExtension_ = nil; +} + +// Call this before using the readOnlySemaphore_. This ensures it is created only once. +void GPBPrepareReadOnlySemaphore(GPBMessage *self) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + + // Create the semaphore on demand (rather than init) as developers might not cause them + // to be needed, and the heap usage can add up. The atomic swap is used to avoid needing + // another lock around creating it. + if (self->readOnlySemaphore_ == nil) { + dispatch_semaphore_t worker = dispatch_semaphore_create(1); + dispatch_semaphore_t expected = nil; + if (!atomic_compare_exchange_strong(&self->readOnlySemaphore_, &expected, worker)) { + dispatch_release(worker); + } +#if defined(__clang_analyzer__) + // The Xcode 9.2 (and 9.3 beta) static analyzer thinks worker is leaked + // (doesn't seem to know about atomic_compare_exchange_strong); so just + // for the analyzer, let it think worker is also released in this case. + else { dispatch_release(worker); } +#endif + } + +#pragma clang diagnostic pop +} + +static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { + if (!self->unknownFields_) { + self->unknownFields_ = [[GPBUnknownFieldSet alloc] init]; + GPBBecomeVisibleToAutocreator(self); + } + return self->unknownFields_; +} + +@implementation GPBMessage + ++ (void)initialize { + Class pbMessageClass = [GPBMessage class]; + if ([self class] == pbMessageClass) { + // This is here to start up the "base" class descriptor. + [self descriptor]; + // Message shares extension method resolving with GPBRootObject so insure + // it is started up at the same time. + (void)[GPBRootObject class]; + } else if ([self superclass] == pbMessageClass) { + // This is here to start up all the "message" subclasses. Just needs to be + // done for the messages, not any of the subclasses. + // This must be done in initialize to enforce thread safety of start up of + // the protocol buffer library. + // Note: The generated code for -descriptor calls + // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject + // subclass for the file. That call chain is what ensures that *Root class + // is started up to support extension resolution off the message class + // (+resolveClassMethod: below) in a thread safe manner. + [self descriptor]; + } +} + ++ (instancetype)allocWithZone:(NSZone *)zone { + // Override alloc to allocate our classes with the additional storage + // required for the instance variables. + GPBDescriptor *descriptor = [self descriptor]; + return NSAllocateObject(self, descriptor->storageSize_, zone); +} + ++ (instancetype)alloc { + return [self allocWithZone:nil]; +} + ++ (GPBDescriptor *)descriptor { + // This is thread safe because it is called from +initialize. + static GPBDescriptor *descriptor = NULL; + static GPBFileDescriptor *fileDescriptor = NULL; + if (!descriptor) { + // Use a dummy file that marks it as proto2 syntax so when used generically + // it supports unknowns/etc. + fileDescriptor = + [[GPBFileDescriptor alloc] initWithPackage:@"internal" + syntax:GPBFileSyntaxProto2]; + + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] + rootClass:Nil + file:fileDescriptor + fields:NULL + fieldCount:0 + storageSize:0 + flags:0]; + } + return descriptor; +} + ++ (instancetype)message { + return [[[self alloc] init] autorelease]; +} + +- (instancetype)init { + if ((self = [super init])) { + messageStorage_ = (GPBMessage_StoragePtr)( + ((uint8_t *)self) + class_getInstanceSize([self class])); + } + + return self; +} + +- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { + return [self initWithData:data extensionRegistry:nil error:errorPtr]; +} + +- (instancetype)initWithData:(NSData *)data + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + if ((self = [self init])) { + @try { + [self mergeFromData:data extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } + } + @catch (NSException *exception) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = ErrorFromException(exception); + } + } +#ifdef DEBUG + if (self && !self.initialized) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif + } + return self; +} + +- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + if ((self = [self init])) { + @try { + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } + } + @catch (NSException *exception) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = ErrorFromException(exception); + } + } +#ifdef DEBUG + if (self && !self.initialized) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif + } + return self; +} + +- (void)dealloc { + [self internalClear:NO]; + NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); + if (readOnlySemaphore_) { + dispatch_release(readOnlySemaphore_); + } + [super dealloc]; +} + +- (void)copyFieldsInto:(GPBMessage *)message + zone:(NSZone *)zone + descriptor:(GPBDescriptor *)descriptor { + // Copy all the storage... + memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); + + GPBFileSyntax syntax = descriptor.file.syntax; + + // Loop over the fields doing fixup... + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (value) { + // We need to copy the array/map, but the catch is for message fields, + // we also need to ensure all the messages as those need copying also. + id newValue; + if (GPBFieldDataTypeIsMessage(field)) { + if (field.fieldType == GPBFieldTypeRepeated) { + NSArray *existingArray = (NSArray *)value; + NSMutableArray *newArray = + [[NSMutableArray alloc] initWithCapacity:existingArray.count]; + newValue = newArray; + for (GPBMessage *msg in existingArray) { + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [newArray addObject:copiedMsg]; + [copiedMsg release]; + } + } else { + if (field.mapKeyDataType == GPBDataTypeString) { + // Map is an NSDictionary. + NSDictionary *existingDict = value; + NSMutableDictionary *newDict = [[NSMutableDictionary alloc] + initWithCapacity:existingDict.count]; + newValue = newDict; + [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, + GPBMessage *msg, + BOOL *stop) { +#pragma unused(stop) + GPBMessage *copiedMsg = [msg copyWithZone:zone]; + [newDict setObject:copiedMsg forKey:key]; + [copiedMsg release]; + }]; + } else { + // Is one of the GPB*ObjectDictionary classes. Type doesn't + // matter, just need one to invoke the selector. + GPBInt32ObjectDictionary *existingDict = value; + newValue = [existingDict deepCopyWithZone:zone]; + } + } + } else { + // Not messages (but is a map/array)... + if (field.fieldType == GPBFieldTypeRepeated) { + if (GPBFieldDataTypeIsObject(field)) { + // NSArray + newValue = [value mutableCopyWithZone:zone]; + } else { + // GPB*Array + newValue = [value copyWithZone:zone]; + } + } else { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + // NSDictionary + newValue = [value mutableCopyWithZone:zone]; + } else { + // Is one of the GPB*Dictionary classes. Type doesn't matter, + // just need one to invoke the selector. + GPBInt32Int32Dictionary *existingDict = value; + newValue = [existingDict copyWithZone:zone]; + } + } + } + // We retain here because the memcpy picked up the pointer value and + // the next call to SetRetainedObject... will release the current value. + [value retain]; + GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, + syntax); + } + } else if (GPBFieldDataTypeIsMessage(field)) { + // For object types, if we have a value, copy it. If we don't, + // zero it to remove the pointer to something that was autocreated + // (and the ptr just got memcpyed). + if (GPBGetHasIvarField(self, field)) { + GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBMessage *newValue = [value copyWithZone:zone]; + // We retain here because the memcpy picked up the pointer value and + // the next call to SetRetainedObject... will release the current value. + [value retain]; + GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, + syntax); + } else { + uint8_t *storage = (uint8_t *)message->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + *typePtr = NULL; + } + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { + // A set string/data value (message picked off above), copy it. + id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + id newValue = [value copyWithZone:zone]; + // We retain here because the memcpy picked up the pointer value and + // the next call to SetRetainedObject... will release the current value. + [value retain]; + GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, + syntax); + } else { + // memcpy took care of the rest of the primitive fields if they were set. + } + } // for (field in descriptor->fields_) +} + +- (id)copyWithZone:(NSZone *)zone { + GPBDescriptor *descriptor = [self descriptor]; + GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init]; + + [self copyFieldsInto:result zone:zone descriptor:descriptor]; + // Make immutable copies of the extra bits. + result->unknownFields_ = [unknownFields_ copyWithZone:zone]; + result->extensionMap_ = CloneExtensionMap(extensionMap_, zone); + return result; +} + +- (void)clear { + [self internalClear:YES]; +} + +- (void)internalClear:(BOOL)zeroStorage { + GPBDescriptor *descriptor = [self descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (arrayOrMap) { + if (field.fieldType == GPBFieldTypeRepeated) { + if (GPBFieldDataTypeIsObject(field)) { + if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) { + GPBAutocreatedArray *autoArray = arrayOrMap; + if (autoArray->_autocreator == self) { + autoArray->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Array. + GPBInt32Array *gpbArray = arrayOrMap; + if (gpbArray->_autocreator == self) { + gpbArray->_autocreator = nil; + } + } + } else { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) { + GPBAutocreatedDictionary *autoDict = arrayOrMap; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Dictionary. + GPBInt32Int32Dictionary *gpbDict = arrayOrMap; + if (gpbDict->_autocreator == self) { + gpbDict->_autocreator = nil; + } + } + } + [arrayOrMap release]; + } + } else if (GPBFieldDataTypeIsMessage(field)) { + GPBClearAutocreatedMessageIvarWithField(self, field); + GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [value release]; + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { + id value = GPBGetObjectIvarWithField(self, field); + [value release]; + } + } + + // GPBClearMessageAutocreator() expects that its caller has already been + // removed from autocreatedExtensionMap_ so we set to nil first. + NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues]; + [autocreatedExtensionMap_ release]; + autocreatedExtensionMap_ = nil; + + // Since we're clearing all of our extensions, make sure that we clear the + // autocreator on any that we've created so they no longer refer to us. + for (GPBMessage *value in autocreatedValues) { + NSCAssert(GPBWasMessageAutocreatedBy(value, self), + @"Autocreated extension does not refer back to self."); + GPBClearMessageAutocreator(value); + } + + [extensionMap_ release]; + extensionMap_ = nil; + [unknownFields_ release]; + unknownFields_ = nil; + + // Note that clearing does not affect autocreator_. If we are being cleared + // because of a dealloc, then autocreator_ should be nil anyway. If we are + // being cleared because someone explicitly clears us, we don't want to + // sever our relationship with our autocreator. + + if (zeroStorage) { + memset(messageStorage_, 0, descriptor->storageSize_); + } +} + +- (BOOL)isInitialized { + GPBDescriptor *descriptor = [self descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.isRequired) { + if (!GPBGetHasIvarField(self, field)) { + return NO; + } + } + if (GPBFieldDataTypeIsMessage(field)) { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + if (field.isRequired) { + GPBMessage *message = GPBGetMessageMessageField(self, field); + if (!message.initialized) { + return NO; + } + } else { + NSAssert(field.isOptional, + @"%@: Single message field %@ not required or optional?", + [self class], field.name); + if (GPBGetHasIvarField(self, field)) { + GPBMessage *message = GPBGetMessageMessageField(self, field); + if (!message.initialized) { + return NO; + } + } + } + } else if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + for (GPBMessage *message in array) { + if (!message.initialized) { + return NO; + } + } + } else { // fieldType == GPBFieldTypeMap + if (field.mapKeyDataType == GPBDataTypeString) { + NSDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { + return NO; + } + } else { + // Real type is GPB*ObjectDictionary, exact type doesn't matter. + GPBInt32ObjectDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (map && ![map isInitialized]) { + return NO; + } + } + } + } + } + + __block BOOL result = YES; + [extensionMap_ + enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, + id obj, + BOOL *stop) { + if (GPBExtensionIsMessage(extension)) { + if (extension.isRepeated) { + for (GPBMessage *msg in obj) { + if (!msg.initialized) { + result = NO; + *stop = YES; + break; + } + } + } else { + GPBMessage *asMsg = obj; + if (!asMsg.initialized) { + result = NO; + *stop = YES; + } + } + } + }]; + return result; +} + +- (GPBDescriptor *)descriptor { + return [[self class] descriptor]; +} + +- (NSData *)data { +#ifdef DEBUG + if (!self.initialized) { + return nil; + } +#endif + NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]]; + GPBCodedOutputStream *stream = + [[GPBCodedOutputStream alloc] initWithData:data]; + @try { + [self writeToCodedOutputStream:stream]; + } + @catch (NSException *exception) { + // This really shouldn't happen. The only way writeToCodedOutputStream: + // could throw is if something in the library has a bug and the + // serializedSize was wrong. +#ifdef DEBUG + NSLog(@"%@: Internal exception while building message data: %@", + [self class], exception); +#endif + data = nil; + } + [stream release]; + return data; +} + +- (NSData *)delimitedData { + size_t serializedSize = [self serializedSize]; + size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize); + NSMutableData *data = + [NSMutableData dataWithLength:(serializedSize + varintSize)]; + GPBCodedOutputStream *stream = + [[GPBCodedOutputStream alloc] initWithData:data]; + @try { + [self writeDelimitedToCodedOutputStream:stream]; + } + @catch (NSException *exception) { + // This really shouldn't happen. The only way writeToCodedOutputStream: + // could throw is if something in the library has a bug and the + // serializedSize was wrong. +#ifdef DEBUG + NSLog(@"%@: Internal exception while building message delimitedData: %@", + [self class], exception); +#endif + // If it happens, truncate. + data.length = 0; + } + [stream release]; + return data; +} + +- (void)writeToOutputStream:(NSOutputStream *)output { + GPBCodedOutputStream *stream = + [[GPBCodedOutputStream alloc] initWithOutputStream:output]; + [self writeToCodedOutputStream:stream]; + [stream release]; +} + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { + GPBDescriptor *descriptor = [self descriptor]; + NSArray *fieldsArray = descriptor->fields_; + NSUInteger fieldCount = fieldsArray.count; + const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; + NSUInteger extensionRangesCount = descriptor.extensionRangesCount; + NSArray *sortedExtensions = + [[extensionMap_ allKeys] sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; + for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { + if (i == fieldCount) { + [self writeExtensionsToCodedOutputStream:output + range:extensionRanges[j++] + sortedExtensions:sortedExtensions]; + } else if (j == extensionRangesCount || + GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { + [self writeField:fieldsArray[i++] toCodedOutputStream:output]; + } else { + [self writeExtensionsToCodedOutputStream:output + range:extensionRanges[j++] + sortedExtensions:sortedExtensions]; + } + } + if (descriptor.isWireFormat) { + [unknownFields_ writeAsMessageSetTo:output]; + } else { + [unknownFields_ writeToCodedOutputStream:output]; + } +} + +- (void)writeDelimitedToOutputStream:(NSOutputStream *)output { + GPBCodedOutputStream *codedOutput = + [[GPBCodedOutputStream alloc] initWithOutputStream:output]; + [self writeDelimitedToCodedOutputStream:codedOutput]; + [codedOutput release]; +} + +- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output { + [output writeRawVarintSizeTAs32:[self serializedSize]]; + [self writeToCodedOutputStream:output]; +} + +- (void)writeField:(GPBFieldDescriptor *)field + toCodedOutputStream:(GPBCodedOutputStream *)output { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + BOOL has = GPBGetHasIvarField(self, field); + if (!has) { + return; + } + } + uint32_t fieldNumber = GPBFieldNumber(field); + +//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE) +//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE) +//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE) +//% case GPBDataType##TYPE: +//% if (fieldType == GPBFieldTypeRepeated) { +//% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; +//% GPB##ARRAY_TYPE##Array *array = +//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% [output write##TYPE##Array:fieldNumber values:array tag:tag]; +//% } else if (fieldType == GPBFieldTypeSingle) { +//% [output write##TYPE:fieldNumber +//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; +//% } else { // fieldType == GPBFieldTypeMap +//% // Exact type here doesn't matter. +//% GPBInt32##ARRAY_TYPE##Dictionary *dict = +//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% [dict writeToCodedOutputStream:output asField:field]; +//% } +//% break; +//% +//%PDDM-DEFINE FIELD_CASE2(TYPE) +//% case GPBDataType##TYPE: +//% if (fieldType == GPBFieldTypeRepeated) { +//% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% [output write##TYPE##Array:fieldNumber values:array]; +//% } else if (fieldType == GPBFieldTypeSingle) { +//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check +//% // again. +//% [output write##TYPE:fieldNumber +//% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; +//% } else { // fieldType == GPBFieldTypeMap +//% // Exact type here doesn't matter. +//% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); +//% GPBDataType mapKeyDataType = field.mapKeyDataType; +//% if (mapKeyDataType == GPBDataTypeString) { +//% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); +//% } else { +//% [dict writeToCodedOutputStream:output asField:field]; +//% } +//% } +//% break; +//% + + switch (GPBGetFieldDataType(field)) { + +//%PDDM-EXPAND FIELD_CASE(Bool, Bool) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeBool: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBBoolArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeBoolArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeBool:fieldNumber + value:GPBGetMessageBoolField(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32BoolDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeFixed32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeFixed32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeFixed32:fieldNumber + value:GPBGetMessageUInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSFixed32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSFixed32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSFixed32:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Float, Float) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeFloat: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBFloatArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeFloatArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeFloat:fieldNumber + value:GPBGetMessageFloatField(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32FloatDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeFixed64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeFixed64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeFixed64:fieldNumber + value:GPBGetMessageUInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSFixed64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSFixed64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSFixed64:fieldNumber + value:GPBGetMessageInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Double, Double) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeDouble: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBDoubleArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeDoubleArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeDouble:fieldNumber + value:GPBGetMessageDoubleField(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32DoubleDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Int32, Int32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeInt32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeInt32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeInt32:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(Int64, Int64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeInt64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeInt64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeInt64:fieldNumber + value:GPBGetMessageInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SInt32, Int32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSInt32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSInt32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSInt32:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(SInt64, Int64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeSInt64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeSInt64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeSInt64:fieldNumber + value:GPBGetMessageInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32Int64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeUInt32: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt32Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeUInt32Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeUInt32:fieldNumber + value:GPBGetMessageUInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt32Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeUInt64: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBUInt64Array *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeUInt64Array:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeUInt64:fieldNumber + value:GPBGetMessageUInt64Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32UInt64Dictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeEnum: + if (fieldType == GPBFieldTypeRepeated) { + uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; + GPBEnumArray *array = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeEnumArray:fieldNumber values:array tag:tag]; + } else if (fieldType == GPBFieldTypeSingle) { + [output writeEnum:fieldNumber + value:GPBGetMessageInt32Field(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + GPBInt32EnumDictionary *dict = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [dict writeToCodedOutputStream:output asField:field]; + } + break; + +//%PDDM-EXPAND FIELD_CASE2(Bytes) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeBytes: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeBytesArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeBytes:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND FIELD_CASE2(String) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeString: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeStringArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeString:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND FIELD_CASE2(Message) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeMessage: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeMessageArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeMessage:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND FIELD_CASE2(Group) +// This block of code is generated, do not edit it directly. + + case GPBDataTypeGroup: + if (fieldType == GPBFieldTypeRepeated) { + NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [output writeGroupArray:fieldNumber values:array]; + } else if (fieldType == GPBFieldTypeSingle) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check + // again. + [output writeGroup:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + } else { // fieldType == GPBFieldTypeMap + // Exact type here doesn't matter. + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { + GPBDictionaryWriteToStreamInternalHelper(output, dict, field); + } else { + [dict writeToCodedOutputStream:output asField:field]; + } + } + break; + +//%PDDM-EXPAND-END (18 expansions) + } +} + +#pragma mark - Extensions + +- (id)getExtension:(GPBExtensionDescriptor *)extension { + CheckExtension(self, extension); + id value = [extensionMap_ objectForKey:extension]; + if (value != nil) { + return value; + } + + // No default for repeated. + if (extension.isRepeated) { + return nil; + } + // Non messages get their default. + if (!GPBExtensionIsMessage(extension)) { + return extension.defaultValue; + } + + // Check for an autocreated value. + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); + value = [autocreatedExtensionMap_ objectForKey:extension]; + if (!value) { + // Auto create the message extensions to match normal fields. + value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, + extension); + + if (autocreatedExtensionMap_ == nil) { + autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; + } + + // We can't simply call setExtension here because that would clear the new + // value's autocreator. + [autocreatedExtensionMap_ setObject:value forKey:extension]; + [value release]; + } + + dispatch_semaphore_signal(readOnlySemaphore_); + return value; +} + +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension { + // This is an internal method so we don't need to call CheckExtension(). + return [extensionMap_ objectForKey:extension]; +} + +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { +#if defined(DEBUG) && DEBUG + CheckExtension(self, extension); +#endif // DEBUG + return nil != [extensionMap_ objectForKey:extension]; +} + +- (NSArray *)extensionsCurrentlySet { + return [extensionMap_ allKeys]; +} + +- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output + range:(GPBExtensionRange)range + sortedExtensions:(NSArray *)sortedExtensions { + uint32_t start = range.start; + uint32_t end = range.end; + for (GPBExtensionDescriptor *extension in sortedExtensions) { + uint32_t fieldNumber = extension.fieldNumber; + if (fieldNumber < start) { + continue; + } + if (fieldNumber >= end) { + break; + } + id value = [extensionMap_ objectForKey:extension]; + GPBWriteExtensionValueToOutputStream(extension, value, output); + } +} + +- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { + if (!value) { + [self clearExtension:extension]; + return; + } + + CheckExtension(self, extension); + + if (extension.repeated) { + [NSException raise:NSInvalidArgumentException + format:@"Must call addExtension() for repeated types."]; + } + + if (extensionMap_ == nil) { + extensionMap_ = [[NSMutableDictionary alloc] init]; + } + + // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION. + // Without it, the compiler complains we're passing an id nullable when + // setObject:forKey: requires a id nonnull for the value. The check for + // !value at the start of the method ensures it isn't nil, but the check + // isn't smart enough to realize that. + [extensionMap_ setObject:(id)value forKey:extension]; + + GPBExtensionDescriptor *descriptor = extension; + + if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { + GPBMessage *autocreatedValue = + [[autocreatedExtensionMap_ objectForKey:extension] retain]; + // Must remove from the map before calling GPBClearMessageAutocreator() so + // that GPBClearMessageAutocreator() knows its safe to clear. + [autocreatedExtensionMap_ removeObjectForKey:extension]; + GPBClearMessageAutocreator(autocreatedValue); + [autocreatedValue release]; + } + + GPBBecomeVisibleToAutocreator(self); +} + +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { + CheckExtension(self, extension); + + if (!extension.repeated) { + [NSException raise:NSInvalidArgumentException + format:@"Must call setExtension() for singular types."]; + } + + if (extensionMap_ == nil) { + extensionMap_ = [[NSMutableDictionary alloc] init]; + } + NSMutableArray *list = [extensionMap_ objectForKey:extension]; + if (list == nil) { + list = [NSMutableArray array]; + [extensionMap_ setObject:list forKey:extension]; + } + + [list addObject:value]; + GPBBecomeVisibleToAutocreator(self); +} + +- (void)setExtension:(GPBExtensionDescriptor *)extension + index:(NSUInteger)idx + value:(id)value { + CheckExtension(self, extension); + + if (!extension.repeated) { + [NSException raise:NSInvalidArgumentException + format:@"Must call setExtension() for singular types."]; + } + + if (extensionMap_ == nil) { + extensionMap_ = [[NSMutableDictionary alloc] init]; + } + + NSMutableArray *list = [extensionMap_ objectForKey:extension]; + + [list replaceObjectAtIndex:idx withObject:value]; + GPBBecomeVisibleToAutocreator(self); +} + +- (void)clearExtension:(GPBExtensionDescriptor *)extension { + CheckExtension(self, extension); + + // Only become visible if there was actually a value to clear. + if ([extensionMap_ objectForKey:extension]) { + [extensionMap_ removeObjectForKey:extension]; + GPBBecomeVisibleToAutocreator(self); + } +} + +#pragma mark - mergeFrom + +- (void)mergeFromData:(NSData *)data + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + [input checkLastTagWas:0]; + [input release]; +} + +#pragma mark - mergeDelimitedFrom + +- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + GPBCodedInputStreamState *state = &input->state_; + if (GPBCodedInputStreamIsAtEnd(state)) { + return; + } + NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); + if (data == nil) { + return; + } + [self mergeFromData:data extensionRegistry:extensionRegistry]; + [data release]; +} + +#pragma mark - Parse From Data Support + ++ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr { + return [self parseFromData:data extensionRegistry:nil error:errorPtr]; +} + ++ (instancetype)parseFromData:(NSData *)data + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + return [[[self alloc] initWithData:data + extensionRegistry:extensionRegistry + error:errorPtr] autorelease]; +} + ++ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + return + [[[self alloc] initWithCodedInputStream:input + extensionRegistry:extensionRegistry + error:errorPtr] autorelease]; +} + +#pragma mark - Parse Delimited From Data Support + ++ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { + GPBMessage *message = [[[self alloc] init] autorelease]; + @try { + [message mergeDelimitedFromCodedInputStream:input + extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } + } + @catch (NSException *exception) { + message = nil; + if (errorPtr) { + *errorPtr = ErrorFromException(exception); + } + } +#ifdef DEBUG + if (message && !message.initialized) { + message = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif + return message; +} + +#pragma mark - Unknown Field Support + +- (GPBUnknownFieldSet *)unknownFields { + return unknownFields_; +} + +- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields { + if (unknownFields != unknownFields_) { + [unknownFields_ release]; + unknownFields_ = [unknownFields copy]; + GPBBecomeVisibleToAutocreator(self); + } +} + +- (void)parseMessageSet:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + uint32_t typeId = 0; + NSData *rawBytes = nil; + GPBExtensionDescriptor *extension = nil; + GPBCodedInputStreamState *state = &input->state_; + while (true) { + uint32_t tag = GPBCodedInputStreamReadTag(state); + if (tag == 0) { + break; + } + + if (tag == GPBWireFormatMessageSetTypeIdTag) { + typeId = GPBCodedInputStreamReadUInt32(state); + if (typeId != 0) { + extension = [extensionRegistry extensionForDescriptor:[self descriptor] + fieldNumber:typeId]; + } + } else if (tag == GPBWireFormatMessageSetMessageTag) { + rawBytes = + [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; + } else { + if (![input skipField:tag]) { + break; + } + } + } + + [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag]; + + if (rawBytes != nil && typeId != 0) { + if (extension != nil) { + GPBCodedInputStream *newInput = + [[GPBCodedInputStream alloc] initWithData:rawBytes]; + GPBExtensionMergeFromInputStream(extension, + extension.packable, + newInput, + extensionRegistry, + self); + [newInput release]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + // rawBytes was created via a NoCopy, so it can be reusing a + // subrange of another NSData that might go out of scope as things + // unwind, so a copy is needed to ensure what is saved in the + // unknown fields stays valid. + NSData *cloned = [NSData dataWithData:rawBytes]; + [unknownFields mergeMessageSetMessage:typeId data:cloned]; + } + } +} + +- (BOOL)parseUnknownField:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + tag:(uint32_t)tag { + GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); + int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); + + GPBDescriptor *descriptor = [self descriptor]; + GPBExtensionDescriptor *extension = + [extensionRegistry extensionForDescriptor:descriptor + fieldNumber:fieldNumber]; + if (extension == nil) { + if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) { + [self parseMessageSet:input extensionRegistry:extensionRegistry]; + return YES; + } + } else { + if (extension.wireType == wireType) { + GPBExtensionMergeFromInputStream(extension, + extension.packable, + input, + extensionRegistry, + self); + return YES; + } + // Primitive, repeated types can be packed on unpacked on the wire, and are + // parsed either way. + if ([extension isRepeated] && + !GPBDataTypeIsObject(extension->description_->dataType) && + (extension.alternateWireType == wireType)) { + GPBExtensionMergeFromInputStream(extension, + !extension.packable, + input, + extensionRegistry, + self); + return YES; + } + } + if ([GPBUnknownFieldSet isFieldTag:tag]) { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + return [unknownFields mergeFieldFrom:tag input:input]; + } else { + return NO; + } +} + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields addUnknownMapEntry:fieldNum value:data]; +} + +#pragma mark - MergeFromCodedInputStream Support + +static void MergeSingleFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ + GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ + GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + + case GPBDataTypeMessage: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readMessage:message extensionRegistry:extensionRegistry]; + } else { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + } + break; + } + + case GPBDataTypeGroup: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + } else { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + } + break; + } + + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(&input->state_); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + } + } // switch +} + +static void MergeRepeatedPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + switch (fieldDataType) { +#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } + CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Float, float, Float) + CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(Double, double, Double) + CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) +#undef CASE_REPEATED_PACKED_POD + + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + NSCAssert(NO, @"Non primitive types can't be packed"); + break; + + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + break; + } + } // switch + } // while(BytesUntilLimit() > 0) + GPBCodedInputStreamPopLimit(state, limit); +} + +static void MergeRepeatedNotPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + switch (GPBGetFieldDataType(field)) { +#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } +#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(state); \ + [(NSMutableArray*)genericArray addObject:val]; \ + [val release]; \ + break; \ + } + CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) + CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) + CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) + CASE_REPEATED_NOT_PACKED_OBJECT(String) +#undef CASE_REPEATED_NOT_PACKED_POD +#undef CASE_NOT_PACKED_OBJECT + case GPBDataTypeMessage: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; + } + case GPBDataTypeGroup: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; + } + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + break; + } + } // switch +} + +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + GPBDescriptor *descriptor = [self descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + GPBCodedInputStreamState *state = &input->state_; + uint32_t tag = 0; + NSUInteger startingIndex = 0; + NSArray *fields = descriptor->fields_; + NSUInteger numFields = fields.count; + while (YES) { + BOOL merged = NO; + tag = GPBCodedInputStreamReadTag(state); + if (tag == 0) { + break; // Reached end. + } + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if (GPBFieldTag(fieldDescriptor) == tag) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + if (fieldType == GPBFieldTypeSingle) { + MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax, + input, extensionRegistry); + // Well formed protos will only have a single field once, advance + // the starting index to the next field. + startingIndex += 1; + } else if (fieldType == GPBFieldTypeRepeated) { + if (fieldDescriptor.isPackable) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + } else { // fieldType == GPBFieldTypeMap + // GPB*Dictionary or NSDictionary, exact type doesn't matter at this + // point. + id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); + [input readMapEntry:map + extensionRegistry:extensionRegistry + field:fieldDescriptor + parentMessage:self]; + } + merged = YES; + break; + } else { + startingIndex += 1; + } + } // for(i < numFields) + + if (!merged && (tag != 0)) { + // Primitive, repeated types can be packed on unpacked on the wire, and + // are parsed either way. The above loop covered tag in the preferred + // for, so this need to check the alternate form. + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && + !GPBFieldDataTypeIsObject(fieldDescriptor) && + (GPBFieldAlternateTag(fieldDescriptor) == tag)) { + BOOL alternateIsPacked = !fieldDescriptor.isPackable; + if (alternateIsPacked) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + merged = YES; + break; + } else { + startingIndex += 1; + } + } + } + + if (!merged) { + if (tag == 0) { + // zero signals EOF / limit reached + return; + } else { + if (![self parseUnknownField:input + extensionRegistry:extensionRegistry + tag:tag]) { + // it's an endgroup tag + return; + } + } + } // if(!merged) + + } // while(YES) +} + +#pragma mark - MergeFrom Support + +- (void)mergeFrom:(GPBMessage *)other { + Class selfClass = [self class]; + Class otherClass = [other class]; + if (!([selfClass isSubclassOfClass:otherClass] || + [otherClass isSubclassOfClass:selfClass])) { + [NSException raise:NSInvalidArgumentException + format:@"Classes must match %@ != %@", selfClass, otherClass]; + } + + // We assume something will be done and become visible. + GPBBecomeVisibleToAutocreator(self); + + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNumber = GPBFieldNumber(field); + if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { + // Other doesn't have the field set, on to the next. + continue; + } + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { + case GPBDataTypeBool: + GPBSetBoolIvarWithFieldInternal( + self, field, GPBGetMessageBoolField(other, field), syntax); + break; + case GPBDataTypeSFixed32: + case GPBDataTypeEnum: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + GPBSetInt32IvarWithFieldInternal( + self, field, GPBGetMessageInt32Field(other, field), syntax); + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + GPBSetUInt32IvarWithFieldInternal( + self, field, GPBGetMessageUInt32Field(other, field), syntax); + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + GPBSetInt64IvarWithFieldInternal( + self, field, GPBGetMessageInt64Field(other, field), syntax); + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + GPBSetUInt64IvarWithFieldInternal( + self, field, GPBGetMessageUInt64Field(other, field), syntax); + break; + case GPBDataTypeFloat: + GPBSetFloatIvarWithFieldInternal( + self, field, GPBGetMessageFloatField(other, field), syntax); + break; + case GPBDataTypeDouble: + GPBSetDoubleIvarWithFieldInternal( + self, field, GPBGetMessageDoubleField(other, field), syntax); + break; + case GPBDataTypeBytes: + case GPBDataTypeString: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); + break; + } + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [message mergeFrom:otherVal]; + } else { + GPBMessage *message = [otherVal copy]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, + syntax); + } + break; + } + } // switch() + } else if (fieldType == GPBFieldTypeRepeated) { + // In the case of a list, they need to be appended, and there is no + // _hasIvar to worry about setting. + id otherArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (otherArray) { + GPBDataType fieldDataType = field->description_->dataType; + if (GPBDataTypeIsObject(fieldDataType)) { + NSMutableArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addObjectsFromArray:otherArray]; + } else if (fieldDataType == GPBDataTypeEnum) { + GPBEnumArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addRawValuesFromArray:otherArray]; + } else { + // The array type doesn't matter, that all implment + // -addValuesFromArray:. + GPBInt32Array *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addValuesFromArray:otherArray]; + } + } + } else { // fieldType = GPBFieldTypeMap + // In the case of a map, they need to be merged, and there is no + // _hasIvar to worry about setting. + id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (otherDict) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = field->description_->dataType; + if (GPBDataTypeIsObject(keyDataType) && + GPBDataTypeIsObject(valueDataType)) { + NSMutableDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } else if (valueDataType == GPBDataTypeEnum) { + // The exact type doesn't matter, just need to know it is a + // GPB*EnumDictionary. + GPBInt32EnumDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addRawEntriesFromDictionary:otherDict]; + } else { + // The exact type doesn't matter, they all implement + // -addEntriesFromDictionary:. + GPBInt32Int32Dictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } + } + } // if (fieldType)..else if...else + } // for(fields) + + // Unknown fields. + if (!unknownFields_) { + [self setUnknownFields:other.unknownFields]; + } else { + [unknownFields_ mergeUnknownFields:other.unknownFields]; + } + + // Extensions + + if (other->extensionMap_.count == 0) { + return; + } + + if (extensionMap_ == nil) { + extensionMap_ = + CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self)); + } else { + for (GPBExtensionDescriptor *extension in other->extensionMap_) { + id otherValue = [other->extensionMap_ objectForKey:extension]; + id value = [extensionMap_ objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); + + if (extension.repeated) { + NSMutableArray *list = value; + if (list == nil) { + list = [[NSMutableArray alloc] init]; + [extensionMap_ setObject:list forKey:extension]; + [list release]; + } + if (isMessageExtension) { + for (GPBMessage *otherListValue in otherValue) { + GPBMessage *copiedValue = [otherListValue copy]; + [list addObject:copiedValue]; + [copiedValue release]; + } + } else { + [list addObjectsFromArray:otherValue]; + } + } else { + if (isMessageExtension) { + if (value) { + [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; + } else { + GPBMessage *copiedValue = [otherValue copy]; + [extensionMap_ setObject:copiedValue forKey:extension]; + [copiedValue release]; + } + } else { + [extensionMap_ setObject:otherValue forKey:extension]; + } + } + + if (isMessageExtension && !extension.isRepeated) { + GPBMessage *autocreatedValue = + [[autocreatedExtensionMap_ objectForKey:extension] retain]; + // Must remove from the map before calling GPBClearMessageAutocreator() + // so that GPBClearMessageAutocreator() knows its safe to clear. + [autocreatedExtensionMap_ removeObjectForKey:extension]; + GPBClearMessageAutocreator(autocreatedValue); + [autocreatedValue release]; + } + } + } +} + +#pragma mark - isEqual: & hash Support + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (![other isKindOfClass:[GPBMessage class]]) { + return NO; + } + GPBMessage *otherMsg = other; + GPBDescriptor *descriptor = [[self class] descriptor]; + if ([[otherMsg class] descriptor] != descriptor) { + return NO; + } + uint8_t *selfStorage = (uint8_t *)messageStorage_; + uint8_t *otherStorage = (uint8_t *)otherMsg->messageStorage_; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + // In the case of a list or map, there is no _hasIvar to worry about. + // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but + // the type doesn't really matter as the objects all support -count and + // -isEqual:. + NSArray *resultMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + NSArray *otherMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + // nil and empty are equal + if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { + if (![resultMapOrArray isEqual:otherMapOrArray]) { + return NO; + } + } + } else { // Single field + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNum = GPBFieldNumber(field); + BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); + BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); + if (selfHas != otherHas) { + return NO; // Differing has values, not equal. + } + if (!selfHas) { + // Same has values, was no, nothing else to check for this field. + continue; + } + // Now compare the values. + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + // Bools are stored in has_bits to avoid needing explicit space in + // the storage structure. + // (the field number passed to the HasIvar helper doesn't really + // matter since the offset is never negative) + BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); + BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0); + if (selfValue != otherValue) { + return NO; + } + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, signed/unsigned doesn't matter for equality. + uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; + uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, signed/unsigned doesn't matter for equality. + uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; + uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + // Type doesn't matter here, they all implement -isEqual:. + id *selfValPtr = (id *)&selfStorage[fieldOffset]; + id *otherValPtr = (id *)&otherStorage[fieldOffset]; + if (![*selfValPtr isEqual:*otherValPtr]) { + return NO; + } + break; + } + } // switch() + } // if(mapOrArray)...else + } // for(fields) + + // nil and empty are equal + if (extensionMap_.count != 0 || otherMsg->extensionMap_.count != 0) { + if (![extensionMap_ isEqual:otherMsg->extensionMap_]) { + return NO; + } + } + + // nil and empty are equal + GPBUnknownFieldSet *otherUnknowns = otherMsg->unknownFields_; + if ([unknownFields_ countOfFields] != 0 || + [otherUnknowns countOfFields] != 0) { + if (![unknownFields_ isEqual:otherUnknowns]) { + return NO; + } + } + + return YES; +} + +// It is very difficult to implement a generic hash for ProtoBuf messages that +// will perform well. If you need hashing on your ProtoBufs (eg you are using +// them as dictionary keys) you will probably want to implement a ProtoBuf +// message specific hash as a category on your protobuf class. Do not make it a +// category on GPBMessage as you will conflict with this hash, and will possibly +// override hash for all generated protobufs. A good implementation of hash will +// be really fast, so we would recommend only hashing protobufs that have an +// identifier field of some kind that you can easily hash. If you implement +// hash, we would strongly recommend overriding isEqual: in your category as +// well, as the default implementation of isEqual: is extremely slow, and may +// drastically affect performance in large sets. +- (NSUInteger)hash { + GPBDescriptor *descriptor = [[self class] descriptor]; + const NSUInteger prime = 19; + uint8_t *storage = (uint8_t *)messageStorage_; + + // Start with the descriptor and then mix it with some instance info. + // Hopefully that will give a spread based on classes and what fields are set. + NSUInteger result = (NSUInteger)descriptor; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + // Exact type doesn't matter, just check if there are any elements. + NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + NSUInteger count = mapOrArray.count; + if (count) { + // NSArray/NSDictionary use count, use the field number and the count. + result = prime * result + GPBFieldNumber(field); + result = prime * result + count; + } + } else if (GPBGetHasIvarField(self, field)) { + // Just using the field number seemed simple/fast, but then a small + // message class where all the same fields are always set (to different + // things would end up all with the same hash, so pull in some data). + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + // Bools are stored in has_bits to avoid needing explicit space in + // the storage structure. + // (the field number passed to the HasIvar helper doesn't really + // matter since the offset is never negative) + BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); + result = prime * result + value; + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, just mix it in. + uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; + result = prime * result + *valPtr; + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, just mix what fits into an NSUInteger in. + uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; + result = prime * result + (NSUInteger)(*valPtr); + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: { + // Type doesn't matter here, they both implement -hash:. + id *valPtr = (id *)&storage[fieldOffset]; + result = prime * result + [*valPtr hash]; + break; + } + + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; + // Could call -hash on the sub message, but that could recurse pretty + // deep; follow the lead of NSArray/NSDictionary and don't really + // recurse for hash, instead use the field number and the descriptor + // of the sub message. Yes, this could suck for a bunch of messages + // where they all only differ in the sub messages, but if you are + // using a message with sub messages for something that needs -hash, + // odds are you are also copying them as keys, and that deep copy + // will also suck. + result = prime * result + GPBFieldNumber(field); + result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; + break; + } + } // switch() + } + } + + // Unknowns and extensions are not included. + + return result; +} + +#pragma mark - Description Support + +- (NSString *)description { + NSString *textFormat = GPBTextFormatForMessage(self, @" "); + NSString *description = [NSString + stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat]; + return description; +} + +#if defined(DEBUG) && DEBUG + +// Xcode 5.1 added support for custom quick look info. +// https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1 +- (id)debugQuickLookObject { + return GPBTextFormatForMessage(self, nil); +} + +#endif // DEBUG + +#pragma mark - SerializedSize + +- (size_t)serializedSize { + GPBDescriptor *descriptor = [[self class] descriptor]; + size_t result = 0; + + // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() + // avoids doing the has check again. + + // Fields. + for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); + + // Single Fields + if (fieldType == GPBFieldTypeSingle) { + BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); + if (!selfHas) { + continue; // Nothing to do. + } + + uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); + + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) + CASE_SINGLE_OBJECT(Message) + CASE_SINGLE_OBJECT(Group) + CASE_SINGLE_POD(Enum, int32_t, Int32) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + } + + // Repeated Fields + } else if (fieldType == GPBFieldTypeRepeated) { + id genericArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + NSUInteger count = [genericArray count]; + if (count == 0) { + continue; // Nothing to add. + } + __block size_t dataSize = 0; + + switch (fieldDataType) { +#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \ + CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) +#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ + case GPBDataType##NAME: { \ + GPB##ARRAY_TYPE##Array *array = genericArray; \ + [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \ + _Pragma("unused(idx, stop)"); \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + }]; \ + break; \ + } +#define CASE_REPEATED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + for (id value in genericArray) { \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + } \ + break; \ + } + CASE_REPEATED_POD(Bool, BOOL, Bool) + CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_POD(Float, float, Float) + CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_POD(Double, double, Double) + CASE_REPEATED_POD(Int32, int32_t, Int32) + CASE_REPEATED_POD(Int64, int64_t, Int64) + CASE_REPEATED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_OBJECT(Bytes) + CASE_REPEATED_OBJECT(String) + CASE_REPEATED_OBJECT(Message) + CASE_REPEATED_OBJECT(Group) + CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) +#undef CASE_REPEATED_POD +#undef CASE_REPEATED_POD_EXTRA +#undef CASE_REPEATED_OBJECT + } // switch + result += dataSize; + size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); + if (fieldDataType == GPBDataTypeGroup) { + // Groups have both a start and an end tag. + tagSize *= 2; + } + if (fieldDescriptor.isPackable) { + result += tagSize; + result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); + } else { + result += count * tagSize; + } + + // Map<> Fields + } else { // fieldType == GPBFieldTypeMap + if (GPBDataTypeIsObject(fieldDataType) && + (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { + // If key type was string, then the map is an NSDictionary. + NSDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + if (map) { + result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor); + } + } else { + // Type will be GPB*GroupDictionary, exact type doesn't matter. + GPBInt32Int32Dictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + result += [map computeSerializedSizeAsField:fieldDescriptor]; + } + } + } // for(fields) + + // Add any unknown fields. + if (descriptor.wireFormat) { + result += [unknownFields_ serializedSizeAsMessageSet]; + } else { + result += [unknownFields_ serializedSize]; + } + + // Add any extensions. + for (GPBExtensionDescriptor *extension in extensionMap_) { + id value = [extensionMap_ objectForKey:extension]; + result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); + } + + return result; +} + +#pragma mark - Resolve Methods Support + +typedef struct ResolveIvarAccessorMethodResult { + IMP impToAdd; + SEL encodingSelector; +} ResolveIvarAccessorMethodResult; + +// |field| can be __unsafe_unretained because they are created at startup +// and are essentially global. No need to pay for retain/release when +// they are captured in blocks. +static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_GET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetMessage##TRUE_NAME##Field(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } +#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetObjectIvarWithField(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } + CASE_GET(Bool, BOOL, Bool) + CASE_GET(Fixed32, uint32_t, UInt32) + CASE_GET(SFixed32, int32_t, Int32) + CASE_GET(Float, float, Float) + CASE_GET(Fixed64, uint64_t, UInt64) + CASE_GET(SFixed64, int64_t, Int64) + CASE_GET(Double, double, Double) + CASE_GET(Int32, int32_t, Int32) + CASE_GET(Int64, int64_t, Int64) + CASE_GET(SInt32, int32_t, Int32) + CASE_GET(SInt64, int64_t, Int64) + CASE_GET(UInt32, uint32_t, UInt32) + CASE_GET(UInt64, uint64_t, UInt64) + CASE_GET_OBJECT(Bytes, id, Object) + CASE_GET_OBJECT(String, id, Object) + CASE_GET_OBJECT(Message, id, Object) + CASE_GET_OBJECT(Group, id, Object) + CASE_GET(Enum, int32_t, Enum) +#undef CASE_GET + } +} + +// See comment about __unsafe_unretained on ResolveIvarGet. +static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, + GPBFileSyntax syntax, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ + return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } +#define CASE_SET_COPY(NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \ + return GPBSetRetainedObjectIvarWithFieldInternal(obj, field, [value copy], syntax); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } + CASE_SET(Bool, BOOL, Bool) + CASE_SET(Fixed32, uint32_t, UInt32) + CASE_SET(SFixed32, int32_t, Int32) + CASE_SET(Float, float, Float) + CASE_SET(Fixed64, uint64_t, UInt64) + CASE_SET(SFixed64, int64_t, Int64) + CASE_SET(Double, double, Double) + CASE_SET(Int32, int32_t, Int32) + CASE_SET(Int64, int64_t, Int64) + CASE_SET(SInt32, int32_t, Int32) + CASE_SET(SInt64, int64_t, Int64) + CASE_SET(UInt32, uint32_t, UInt32) + CASE_SET(UInt64, uint64_t, UInt64) + CASE_SET_COPY(Bytes) + CASE_SET_COPY(String) + CASE_SET(Message, id, Object) + CASE_SET(Group, id, Object) + CASE_SET(Enum, int32_t, Enum) +#undef CASE_SET + } +} + ++ (BOOL)resolveInstanceMethod:(SEL)sel { + const GPBDescriptor *descriptor = [self descriptor]; + if (!descriptor) { + return [super resolveInstanceMethod:sel]; + } + + // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given + // message should not have has support (done in GPBDescriptor.m), so there is + // no need for checks here to see if has*/setHas* are allowed. + ResolveIvarAccessorMethodResult result = {NULL, NULL}; + + // See comment about __unsafe_unretained on ResolveIvarGet. + for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) { + BOOL isMapOrArray = GPBFieldIsMapOrArray(field); + if (!isMapOrArray) { + // Single fields. + if (sel == field->getSel_) { + ResolveIvarGet(field, &result); + break; + } else if (sel == field->setSel_) { + ResolveIvarSet(field, descriptor.file.syntax, &result); + break; + } else if (sel == field->hasOrCountSel_) { + int32_t index = GPBFieldHasIndex(field); + uint32_t fieldNum = GPBFieldNumber(field); + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GPBGetHasIvar(obj, index, fieldNum); + }); + result.encodingSelector = @selector(getBool); + break; + } else if (sel == field->setHasSel_) { + result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { + if (value) { + [NSException raise:NSInvalidArgumentException + format:@"%@: %@ can only be set to NO (to clear field).", + [obj class], + NSStringFromSelector(field->setHasSel_)]; + } + GPBClearMessageField(obj, field); + }); + result.encodingSelector = @selector(setBool:); + break; + } else { + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof && (sel == oneof->caseSel_)) { + int32_t index = GPBFieldHasIndex(field); + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GPBGetHasOneof(obj, index); + }); + result.encodingSelector = @selector(getEnum); + break; + } + } + } else { + // map<>/repeated fields. + if (sel == field->getSel_) { + if (field.fieldType == GPBFieldTypeRepeated) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GetArrayIvarWithField(obj, field); + }); + } else { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + return GetMapIvarWithField(obj, field); + }); + } + result.encodingSelector = @selector(getArray); + break; + } else if (sel == field->setSel_) { + // Local for syntax so the block can directly capture it and not the + // full lookup. + const GPBFileSyntax syntax = descriptor.file.syntax; + result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { + GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); + }); + result.encodingSelector = @selector(setArray:); + break; + } else if (sel == field->hasOrCountSel_) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + // Type doesn't matter, all *Array and *Dictionary types support + // -count. + NSArray *arrayOrMap = + GPBGetObjectIvarWithFieldNoAutocreate(obj, field); + return [arrayOrMap count]; + }); + result.encodingSelector = @selector(getArrayCount); + break; + } + } + } + if (result.impToAdd) { + const char *encoding = + GPBMessageEncodingForSelector(result.encodingSelector, YES); + Class msgClass = descriptor.messageClass; + BOOL methodAdded = class_addMethod(msgClass, sel, result.impToAdd, encoding); + // class_addMethod() is documented as also failing if the method was already + // added; so we check if the method is already there and return success so + // the method dispatch will still happen. Why would it already be added? + // Two threads could cause the same method to be bound at the same time, + // but only one will actually bind it; the other still needs to return true + // so things will dispatch. + if (!methodAdded) { + methodAdded = GPBClassHasSel(msgClass, sel); + } + return methodAdded; + } + return [super resolveInstanceMethod:sel]; +} + ++ (BOOL)resolveClassMethod:(SEL)sel { + // Extensions scoped to a Message and looked up via class methods. + if (GPBResolveExtensionClassMethod([self descriptor].messageClass, sel)) { + return YES; + } + return [super resolveClassMethod:sel]; +} + +#pragma mark - NSCoding Support + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [self init]; + if (self) { + NSData *data = + [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; + if (data.length) { + [self mergeFromData:data extensionRegistry:nil]; + } + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { +#if defined(DEBUG) && DEBUG + if (extensionMap_.count) { + // Hint to go along with the docs on GPBMessage about this. + // + // Note: This is incomplete, in that it only checked the "root" message, + // if a sub message in a field has extensions, the issue still exists. A + // recursive check could be done here (like the work in + // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to + // be expensive and could slow down serialization in DEBUG enought to cause + // developers other problems. + NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it" + @" has %ld extensions; when read back in, those fields will be" + @" in the unknownFields property instead.", + [self class], (long)extensionMap_.count); + } +#endif + NSData *data = [self data]; + if (data.length) { + [aCoder encodeObject:data forKey:kGPBDataCoderKey]; + } +} + +#pragma mark - KVC Support + ++ (BOOL)accessInstanceVariablesDirectly { + // Make sure KVC doesn't use instance variables. + return NO; +} + +@end + +#pragma mark - Messages from GPBUtilities.h but defined here for access to helpers. + +// Only exists for public api, no core code should use this. +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } +#endif + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + return GetOrCreateArrayIvarWithField(self, field, syntax); +} + +// Only exists for public api, no core code should use this. +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } +#endif + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + return GetOrCreateMapIvarWithField(self, field, syntax); +} + +id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + return *typePtr; + } + // Not set... + + // Non messages (string/data), get their default. + if (!GPBFieldDataTypeIsMessage(field)) { + return field.defaultValue.valueMessage; + } + + GPBPrepareReadOnlySemaphore(self); + dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); + GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!result) { + // For non repeated messages, create the object, set it and return it. + // This object will not initially be visible via GPBGetHasIvar, so + // we save its creator so it can become visible if it's mutated later. + result = GPBCreateMessageWithAutocreator(field.msgClass, self, field); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result); + } + dispatch_semaphore_signal(self->readOnlySemaphore_); + return result; +} + +#pragma clang diagnostic pop diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage_PackagePrivate.h new file mode 100644 index 0000000..ca10983 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBMessage_PackagePrivate.h @@ -0,0 +1,124 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is private to the ProtobolBuffers library and must NOT be +// included by any sources outside this library. The contents of this file are +// subject to change at any time without notice. + +#import "GPBMessage.h" + +// TODO: Remove this import. Older generated code use the OSAtomic* apis, +// so anyone that hasn't regenerated says building by having this. After +// enough time has passed, this likely can be removed as folks should have +// regenerated. +#import + +#import "GPBBootstrap.h" + +typedef struct GPBMessage_Storage { + uint32_t _has_storage_[0]; +} GPBMessage_Storage; + +typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; + +@interface GPBMessage () { + @package + // NOTE: Because of the +allocWithZone code using NSAllocateObject(), + // this structure should ideally always be kept pointer aligned where the + // real storage starts is also pointer aligned. The compiler/runtime already + // do this, but it may not be documented. + + // A pointer to the actual fields of the subclasses. The actual structure + // pointed to by this pointer will depend on the subclass. + // All of the actual structures will start the same as + // GPBMessage_Storage with _has_storage__ as the first field. + // Kept public because static functions need to access it. + GPBMessage_StoragePtr messageStorage_; +} + +// Gets an extension value without autocreating the result if not found. (i.e. +// returns nil if the extension is not set) +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension; + +// Parses a message of this type from the input and merges it with this +// message. +// +// Warning: This does not verify that all required fields are present in +// the input message. +// Note: The caller should call +// -[CodedInputStream checkLastTagWas:] after calling this to +// verify that the last tag seen was the appropriate end-group tag, +// or zero for EOF. +// NOTE: This will throw if there is an error while parsing. +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + +// Parses the next delimited message of this type from the input and merges it +// with this message. +- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input + extensionRegistry: + (GPBExtensionRegistry *)extensionRegistry; + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data; + +@end + +CF_EXTERN_C_BEGIN + + +// Call this before using the readOnlySemaphore_. This ensures it is created only once. +void GPBPrepareReadOnlySemaphore(GPBMessage *self); + +// Returns a new instance that was automatically created by |autocreator| for +// its field |field|. +GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, + GPBMessage *autocreator, + GPBFieldDescriptor *field) + __attribute__((ns_returns_retained)); + +// Returns whether |message| autocreated this message. This is NO if the message +// was not autocreated by |message| or if it has been mutated since +// autocreation. +BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent); + +// Call this when you mutate a message. It will cause the message to become +// visible to its autocreator. +void GPBBecomeVisibleToAutocreator(GPBMessage *self); + +// Call this when an array/dictionary is mutated so the parent message that +// autocreated it can react. +void GPBAutocreatedArrayModified(GPBMessage *self, id array); +void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary); + +// Clear the autocreator, if any. Asserts if the autocreator still has an +// autocreated reference to this message. +void GPBClearMessageAutocreator(GPBMessage *self); + +CF_EXTERN_C_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBProtocolBuffers.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBProtocolBuffers.h new file mode 100644 index 0000000..68d8854 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBProtocolBuffers.h @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBBootstrap.h" + +#import "GPBArray.h" +#import "GPBCodedInputStream.h" +#import "GPBCodedOutputStream.h" +#import "GPBDescriptor.h" +#import "GPBDictionary.h" +#import "GPBExtensionRegistry.h" +#import "GPBMessage.h" +#import "GPBRootObject.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFieldSet.h" +#import "GPBUtilities.h" +#import "GPBWellKnownTypes.h" +#import "GPBWireFormat.h" + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +// Well-known proto types +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import +#else + #import "google/protobuf/Any.pbobjc.h" + #import "google/protobuf/Api.pbobjc.h" + #import "google/protobuf/Duration.pbobjc.h" + #import "google/protobuf/Empty.pbobjc.h" + #import "google/protobuf/FieldMask.pbobjc.h" + #import "google/protobuf/SourceContext.pbobjc.h" + #import "google/protobuf/Struct.pbobjc.h" + #import "google/protobuf/Timestamp.pbobjc.h" + #import "google/protobuf/Type.pbobjc.h" + #import "google/protobuf/Wrappers.pbobjc.h" +#endif diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBProtocolBuffers_RuntimeSupport.h new file mode 100644 index 0000000..04dde62 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBProtocolBuffers_RuntimeSupport.h @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This header is meant to only be used by the generated source, it should not +// be included in code using protocol buffers. + +#import "GPBBootstrap.h" + +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBExtensionInternals.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBRootObject_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject.h new file mode 100644 index 0000000..d2e2aeb --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject.h @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBExtensionRegistry; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Every generated proto file defines a local "Root" class that exposes a + * GPBExtensionRegistry for all the extensions defined by that file and + * the files it depends on. + **/ +@interface GPBRootObject : NSObject + +/** + * @return An extension registry for the given file and all the files it depends + * on. + **/ ++ (GPBExtensionRegistry *)extensionRegistry; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject.m new file mode 100644 index 0000000..bad2f9a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject.m @@ -0,0 +1,245 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBRootObject_PackagePrivate.h" + +#import + +#import + +#import "GPBDescriptor.h" +#import "GPBExtensionRegistry.h" +#import "GPBUtilities_PackagePrivate.h" + +@interface GPBExtensionDescriptor (GPBRootObject) +// Get singletonName as a c string. +- (const char *)singletonNameC; +@end + +// We need some object to conform to the MessageSignatureProtocol to make sure +// the selectors in it are recorded in our Objective C runtime information. +// GPBMessage is arguably the more "obvious" choice, but given that all messages +// inherit from GPBMessage, conflicts seem likely, so we are using GPBRootObject +// instead. +@interface GPBRootObject () +@end + +@implementation GPBRootObject + +// Taken from http://www.burtleburtle.net/bob/hash/doobs.html +// Public Domain +static uint32_t jenkins_one_at_a_time_hash(const char *key) { + uint32_t hash = 0; + for (uint32_t i = 0; key[i] != '\0'; ++i) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; +} + +// Key methods for our custom CFDictionary. +// Note that the dictionary lasts for the lifetime of our app, so no need +// to worry about deallocation. All of the items are added to it at +// startup, and so the keys don't need to be retained/released. +// Keys are NULL terminated char *. +static const void *GPBRootExtensionKeyRetain(CFAllocatorRef allocator, + const void *value) { +#pragma unused(allocator) + return value; +} + +static void GPBRootExtensionKeyRelease(CFAllocatorRef allocator, + const void *value) { +#pragma unused(allocator) +#pragma unused(value) +} + +static CFStringRef GPBRootExtensionCopyKeyDescription(const void *value) { + const char *key = (const char *)value; + return CFStringCreateWithCString(kCFAllocatorDefault, key, + kCFStringEncodingUTF8); +} + +static Boolean GPBRootExtensionKeyEqual(const void *value1, + const void *value2) { + const char *key1 = (const char *)value1; + const char *key2 = (const char *)value2; + return strcmp(key1, key2) == 0; +} + +static CFHashCode GPBRootExtensionKeyHash(const void *value) { + const char *key = (const char *)value; + return jenkins_one_at_a_time_hash(key); +} + +// NOTE: OSSpinLock may seem like a good fit here but Apple engineers have +// pointed out that they are vulnerable to live locking on iOS in cases of +// priority inversion: +// http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ +// https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html +static dispatch_semaphore_t gExtensionSingletonDictionarySemaphore; +static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; +static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL; + ++ (void)initialize { + // Ensure the global is started up. + if (!gExtensionSingletonDictionary) { + gExtensionSingletonDictionarySemaphore = dispatch_semaphore_create(1); + CFDictionaryKeyCallBacks keyCallBacks = { + // See description above for reason for using custom dictionary. + 0, + GPBRootExtensionKeyRetain, + GPBRootExtensionKeyRelease, + GPBRootExtensionCopyKeyDescription, + GPBRootExtensionKeyEqual, + GPBRootExtensionKeyHash, + }; + gExtensionSingletonDictionary = + CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, + &kCFTypeDictionaryValueCallBacks); + gDefaultExtensionRegistry = [[GPBExtensionRegistry alloc] init]; + } + + if ([self superclass] == [GPBRootObject class]) { + // This is here to start up all the per file "Root" subclasses. + // This must be done in initialize to enforce thread safety of start up of + // the protocol buffer library. + [self extensionRegistry]; + } +} + ++ (GPBExtensionRegistry *)extensionRegistry { + // Is overridden in all the subclasses that provide extensions to provide the + // per class one. + return gDefaultExtensionRegistry; +} + ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field { + const char *key = [field singletonNameC]; + dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore, + DISPATCH_TIME_FOREVER); + CFDictionarySetValue(gExtensionSingletonDictionary, key, field); + dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore); +} + +static id ExtensionForName(id self, SEL _cmd) { + // Really fast way of doing "classname_selName". + // This came up as a hotspot (creation of NSString *) when accessing a + // lot of extensions. + const char *selName = sel_getName(_cmd); + if (selName[0] == '_') { + return nil; // Apple internal selector. + } + size_t selNameLen = 0; + while (1) { + char c = selName[selNameLen]; + if (c == '\0') { // String end. + break; + } + if (c == ':') { + return nil; // Selector took an arg, not one of the runtime methods. + } + ++selNameLen; + } + + const char *className = class_getName(self); + size_t classNameLen = strlen(className); + char key[classNameLen + selNameLen + 2]; + memcpy(key, className, classNameLen); + key[classNameLen] = '_'; + memcpy(&key[classNameLen + 1], selName, selNameLen); + key[classNameLen + 1 + selNameLen] = '\0'; + + // NOTE: Even though this method is called from another C function, + // gExtensionSingletonDictionarySemaphore and gExtensionSingletonDictionary + // will always be initialized. This is because this call flow is just to + // lookup the Extension, meaning the code is calling an Extension class + // message on a Message or Root class. This guarantees that the class was + // initialized and Message classes ensure their Root was also initialized. + NSAssert(gExtensionSingletonDictionary, @"Startup order broken!"); + + dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore, + DISPATCH_TIME_FOREVER); + id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key); + // We can't remove the key from the dictionary here (as an optimization), + // two threads could have gone into +resolveClassMethod: for the same method, + // and ended up here; there's no way to ensure both return YES without letting + // both try to wire in the method. + dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore); + return extension; +} + +BOOL GPBResolveExtensionClassMethod(Class self, SEL sel) { + // Another option would be to register the extensions with the class at + // globallyRegisterExtension: + // Timing the two solutions, this solution turned out to be much faster + // and reduced startup time, and runtime memory. + // The advantage to globallyRegisterExtension is that it would reduce the + // size of the protos somewhat because the singletonNameC wouldn't need + // to include the class name. For a class with a lot of extensions it + // can add up. You could also significantly reduce the code complexity of this + // file. + id extension = ExtensionForName(self, sel); + if (extension != nil) { + const char *encoding = + GPBMessageEncodingForSelector(@selector(getClassValue), NO); + Class metaClass = objc_getMetaClass(class_getName(self)); + IMP imp = imp_implementationWithBlock(^(id obj) { +#pragma unused(obj) + return extension; + }); + BOOL methodAdded = class_addMethod(metaClass, sel, imp, encoding); + // class_addMethod() is documented as also failing if the method was already + // added; so we check if the method is already there and return success so + // the method dispatch will still happen. Why would it already be added? + // Two threads could cause the same method to be bound at the same time, + // but only one will actually bind it; the other still needs to return true + // so things will dispatch. + if (!methodAdded) { + methodAdded = GPBClassHasSel(metaClass, sel); + } + return methodAdded; + } + return NO; +} + + ++ (BOOL)resolveClassMethod:(SEL)sel { + if (GPBResolveExtensionClassMethod(self, sel)) { + return YES; + } + return [super resolveClassMethod:sel]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject_PackagePrivate.h new file mode 100644 index 0000000..3c8f09c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRootObject_PackagePrivate.h @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBRootObject.h" + +@class GPBExtensionDescriptor; + +@interface GPBRootObject () + +// Globally register. ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field; + +@end + +// Returns YES if the selector was resolved and added to the class, +// NO otherwise. +BOOL GPBResolveExtensionClassMethod(Class self, SEL sel); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRuntimeTypes.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRuntimeTypes.h new file mode 100644 index 0000000..4d55206 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBRuntimeTypes.h @@ -0,0 +1,144 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBBootstrap.h" + +@class GPBEnumDescriptor; +@class GPBMessage; +@class GPBInt32Array; + +/** + * Verifies that a given value can be represented by an enum type. + * */ +typedef BOOL (*GPBEnumValidationFunc)(int32_t); + +/** + * Fetches an EnumDescriptor. + * */ +typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void); + +/** + * Magic value used at runtime to indicate an enum value that wasn't know at + * compile time. + * */ +enum { + kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF, +}; + +/** + * A union for storing all possible Protobuf values. Note that owner is + * responsible for memory management of object types. + * */ +typedef union { + BOOL valueBool; + int32_t valueInt32; + int64_t valueInt64; + uint32_t valueUInt32; + uint64_t valueUInt64; + float valueFloat; + double valueDouble; + GPB_UNSAFE_UNRETAINED NSData *valueData; + GPB_UNSAFE_UNRETAINED NSString *valueString; + GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage; + int32_t valueEnum; +} GPBGenericValue; + +/** + * Enum listing the possible data types that a field can contain. + * + * @note Do not change the order of this enum (or add things to it) without + * thinking about it very carefully. There are several things that depend + * on the order. + * */ +typedef NS_ENUM(uint8_t, GPBDataType) { + /** Field contains boolean value(s). */ + GPBDataTypeBool = 0, + /** Field contains unsigned 4 byte value(s). */ + GPBDataTypeFixed32, + /** Field contains signed 4 byte value(s). */ + GPBDataTypeSFixed32, + /** Field contains float value(s). */ + GPBDataTypeFloat, + /** Field contains unsigned 8 byte value(s). */ + GPBDataTypeFixed64, + /** Field contains signed 8 byte value(s). */ + GPBDataTypeSFixed64, + /** Field contains double value(s). */ + GPBDataTypeDouble, + /** + * Field contains variable length value(s). Inefficient for encoding negative + * numbers – if your field is likely to have negative values, use + * GPBDataTypeSInt32 instead. + **/ + GPBDataTypeInt32, + /** + * Field contains variable length value(s). Inefficient for encoding negative + * numbers – if your field is likely to have negative values, use + * GPBDataTypeSInt64 instead. + **/ + GPBDataTypeInt64, + /** Field contains signed variable length integer value(s). */ + GPBDataTypeSInt32, + /** Field contains signed variable length integer value(s). */ + GPBDataTypeSInt64, + /** Field contains unsigned variable length integer value(s). */ + GPBDataTypeUInt32, + /** Field contains unsigned variable length integer value(s). */ + GPBDataTypeUInt64, + /** Field contains an arbitrary sequence of bytes. */ + GPBDataTypeBytes, + /** Field contains UTF-8 encoded or 7-bit ASCII text. */ + GPBDataTypeString, + /** Field contains message type(s). */ + GPBDataTypeMessage, + /** Field contains message type(s). */ + GPBDataTypeGroup, + /** Field contains enum value(s). */ + GPBDataTypeEnum, +}; + +enum { + /** + * A count of the number of types in GPBDataType. Separated out from the + * GPBDataType enum to avoid warnings regarding not handling GPBDataType_Count + * in switch statements. + **/ + GPBDataType_Count = GPBDataTypeEnum + 1 +}; + +/** An extension range. */ +typedef struct GPBExtensionRange { + /** Inclusive. */ + uint32_t start; + /** Exclusive. */ + uint32_t end; +} GPBExtensionRange; diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField.h new file mode 100644 index 0000000..5b96023 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField.h @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBCodedOutputStream; +@class GPBUInt32Array; +@class GPBUInt64Array; +@class GPBUnknownFieldSet; + +NS_ASSUME_NONNULL_BEGIN +/** + * Store an unknown field. These are used in conjunction with + * GPBUnknownFieldSet. + **/ +@interface GPBUnknownField : NSObject + +/** Initialize a field with the given number. */ +- (instancetype)initWithNumber:(int32_t)number; + +/** The field number the data is stored under. */ +@property(nonatomic, readonly, assign) int32_t number; + +/** An array of varint values for this field. */ +@property(nonatomic, readonly, strong) GPBUInt64Array *varintList; + +/** An array of fixed32 values for this field. */ +@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List; + +/** An array of fixed64 values for this field. */ +@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List; + +/** An array of data values for this field. */ +@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList; + +/** An array of groups of values for this field. */ +@property(nonatomic, readonly, strong) NSArray *groupList; + +/** + * Add a value to the varintList. + * + * @param value The value to add. + **/ +- (void)addVarint:(uint64_t)value; +/** + * Add a value to the fixed32List. + * + * @param value The value to add. + **/ +- (void)addFixed32:(uint32_t)value; +/** + * Add a value to the fixed64List. + * + * @param value The value to add. + **/ +- (void)addFixed64:(uint64_t)value; +/** + * Add a value to the lengthDelimitedList. + * + * @param value The value to add. + **/ +- (void)addLengthDelimited:(NSData *)value; +/** + * Add a value to the groupList. + * + * @param value The value to add. + **/ +- (void)addGroup:(GPBUnknownFieldSet *)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField.m new file mode 100644 index 0000000..7fa8cad --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField.m @@ -0,0 +1,337 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBUnknownField_PackagePrivate.h" + +#import "GPBArray.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBUnknownFieldSet.h" + +@implementation GPBUnknownField { + @protected + int32_t number_; + GPBUInt64Array *mutableVarintList_; + GPBUInt32Array *mutableFixed32List_; + GPBUInt64Array *mutableFixed64List_; + NSMutableArray *mutableLengthDelimitedList_; + NSMutableArray *mutableGroupList_; +} + +@synthesize number = number_; +@synthesize varintList = mutableVarintList_; +@synthesize fixed32List = mutableFixed32List_; +@synthesize fixed64List = mutableFixed64List_; +@synthesize lengthDelimitedList = mutableLengthDelimitedList_; +@synthesize groupList = mutableGroupList_; + +- (instancetype)initWithNumber:(int32_t)number { + if ((self = [super init])) { + number_ = number; + } + return self; +} + +- (void)dealloc { + [mutableVarintList_ release]; + [mutableFixed32List_ release]; + [mutableFixed64List_ release]; + [mutableLengthDelimitedList_ release]; + [mutableGroupList_ release]; + + [super dealloc]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (id)copyWithZone:(NSZone *)zone { + GPBUnknownField *result = + [[GPBUnknownField allocWithZone:zone] initWithNumber:number_]; + result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; + result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; + result->mutableLengthDelimitedList_ = + [mutableLengthDelimitedList_ mutableCopyWithZone:zone]; + result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone]; + if (mutableGroupList_.count) { + result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone] + initWithCapacity:mutableGroupList_.count]; + for (GPBUnknownFieldSet *group in mutableGroupList_) { + GPBUnknownFieldSet *copied = [group copyWithZone:zone]; + [result->mutableGroupList_ addObject:copied]; + [copied release]; + } + } + return result; +} + +- (BOOL)isEqual:(id)object { + if (self == object) return YES; + if (![object isKindOfClass:[GPBUnknownField class]]) return NO; + GPBUnknownField *field = (GPBUnknownField *)object; + if (number_ != field->number_) return NO; + BOOL equalVarint = + (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || + [mutableVarintList_ isEqual:field->mutableVarintList_]; + if (!equalVarint) return NO; + BOOL equalFixed32 = (mutableFixed32List_.count == 0 && + field->mutableFixed32List_.count == 0) || + [mutableFixed32List_ isEqual:field->mutableFixed32List_]; + if (!equalFixed32) return NO; + BOOL equalFixed64 = (mutableFixed64List_.count == 0 && + field->mutableFixed64List_.count == 0) || + [mutableFixed64List_ isEqual:field->mutableFixed64List_]; + if (!equalFixed64) return NO; + BOOL equalLDList = + (mutableLengthDelimitedList_.count == 0 && + field->mutableLengthDelimitedList_.count == 0) || + [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_]; + if (!equalLDList) return NO; + BOOL equalGroupList = + (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) || + [mutableGroupList_ isEqual:field->mutableGroupList_]; + if (!equalGroupList) return NO; + return YES; +} + +- (NSUInteger)hash { + // Just mix the hashes of the possible sub arrays. + const int prime = 31; + NSUInteger result = prime + [mutableVarintList_ hash]; + result = prime * result + [mutableFixed32List_ hash]; + result = prime * result + [mutableFixed64List_ hash]; + result = prime * result + [mutableLengthDelimitedList_ hash]; + result = prime * result + [mutableGroupList_ hash]; + return result; +} + +- (void)writeToOutput:(GPBCodedOutputStream *)output { + NSUInteger count = mutableVarintList_.count; + if (count > 0) { + [output writeUInt64Array:number_ values:mutableVarintList_ tag:0]; + } + count = mutableFixed32List_.count; + if (count > 0) { + [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0]; + } + count = mutableFixed64List_.count; + if (count > 0) { + [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0]; + } + count = mutableLengthDelimitedList_.count; + if (count > 0) { + [output writeBytesArray:number_ values:mutableLengthDelimitedList_]; + } + count = mutableGroupList_.count; + if (count > 0) { + [output writeUnknownGroupArray:number_ values:mutableGroupList_]; + } +} + +- (size_t)serializedSize { + __block size_t result = 0; + int32_t number = number_; + [mutableVarintList_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeUInt64Size(number, value); + }]; + + [mutableFixed32List_ + enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeFixed32Size(number, value); + }]; + + [mutableFixed64List_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeFixed64Size(number, value); + }]; + + for (NSData *data in mutableLengthDelimitedList_) { + result += GPBComputeBytesSize(number, data); + } + + for (GPBUnknownFieldSet *set in mutableGroupList_) { + result += GPBComputeUnknownGroupSize(number, set); + } + + return result; +} + +- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output { + for (NSData *data in mutableLengthDelimitedList_) { + [output writeRawMessageSetExtension:number_ value:data]; + } +} + +- (size_t)serializedSizeAsMessageSetExtension { + size_t result = 0; + for (NSData *data in mutableLengthDelimitedList_) { + result += GPBComputeRawMessageSetExtensionSize(number_, data); + } + return result; +} + +- (NSString *)description { + NSMutableString *description = + [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n", + [self class], self, number_]; + [mutableVarintList_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%llu\n", value]; + }]; + + [mutableFixed32List_ + enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%u\n", value]; + }]; + + [mutableFixed64List_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%llu\n", value]; + }]; + + for (NSData *data in mutableLengthDelimitedList_) { + [description appendFormat:@"\t%@\n", data]; + } + + for (GPBUnknownFieldSet *set in mutableGroupList_) { + [description appendFormat:@"\t%@\n", set]; + } + [description appendString:@"}"]; + return description; +} + +- (void)mergeFromField:(GPBUnknownField *)other { + GPBUInt64Array *otherVarintList = other.varintList; + if (otherVarintList.count > 0) { + if (mutableVarintList_ == nil) { + mutableVarintList_ = [otherVarintList copy]; + } else { + [mutableVarintList_ addValuesFromArray:otherVarintList]; + } + } + + GPBUInt32Array *otherFixed32List = other.fixed32List; + if (otherFixed32List.count > 0) { + if (mutableFixed32List_ == nil) { + mutableFixed32List_ = [otherFixed32List copy]; + } else { + [mutableFixed32List_ addValuesFromArray:otherFixed32List]; + } + } + + GPBUInt64Array *otherFixed64List = other.fixed64List; + if (otherFixed64List.count > 0) { + if (mutableFixed64List_ == nil) { + mutableFixed64List_ = [otherFixed64List copy]; + } else { + [mutableFixed64List_ addValuesFromArray:otherFixed64List]; + } + } + + NSArray *otherLengthDelimitedList = other.lengthDelimitedList; + if (otherLengthDelimitedList.count > 0) { + if (mutableLengthDelimitedList_ == nil) { + mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy]; + } else { + [mutableLengthDelimitedList_ + addObjectsFromArray:otherLengthDelimitedList]; + } + } + + NSArray *otherGroupList = other.groupList; + if (otherGroupList.count > 0) { + if (mutableGroupList_ == nil) { + mutableGroupList_ = + [[NSMutableArray alloc] initWithCapacity:otherGroupList.count]; + } + // Make our own mutable copies. + for (GPBUnknownFieldSet *group in otherGroupList) { + GPBUnknownFieldSet *copied = [group copy]; + [mutableGroupList_ addObject:copied]; + [copied release]; + } + } +} + +- (void)addVarint:(uint64_t)value { + if (mutableVarintList_ == nil) { + mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1]; + } else { + [mutableVarintList_ addValue:value]; + } +} + +- (void)addFixed32:(uint32_t)value { + if (mutableFixed32List_ == nil) { + mutableFixed32List_ = + [[GPBUInt32Array alloc] initWithValues:&value count:1]; + } else { + [mutableFixed32List_ addValue:value]; + } +} + +- (void)addFixed64:(uint64_t)value { + if (mutableFixed64List_ == nil) { + mutableFixed64List_ = + [[GPBUInt64Array alloc] initWithValues:&value count:1]; + } else { + [mutableFixed64List_ addValue:value]; + } +} + +- (void)addLengthDelimited:(NSData *)value { + if (mutableLengthDelimitedList_ == nil) { + mutableLengthDelimitedList_ = + [[NSMutableArray alloc] initWithObjects:&value count:1]; + } else { + [mutableLengthDelimitedList_ addObject:value]; + } +} + +- (void)addGroup:(GPBUnknownFieldSet *)value { + if (mutableGroupList_ == nil) { + mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1]; + } else { + [mutableGroupList_ addObject:value]; + } +} + +#pragma clang diagnostic pop + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.h new file mode 100644 index 0000000..1b5f24f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.h @@ -0,0 +1,82 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class GPBUnknownField; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A collection of unknown fields. Fields parsed from the binary representation + * of a message that are unknown end up in an instance of this set. This only + * applies for files declared with the "proto2" syntax. Files declared with the + * "proto3" syntax discard the unknown values. + **/ +@interface GPBUnknownFieldSet : NSObject + +/** + * Tests to see if the given field number has a value. + * + * @param number The field number to check. + * + * @return YES if there is an unknown field for the given field number. + **/ +- (BOOL)hasField:(int32_t)number; + +/** + * Fetches the GPBUnknownField for the given field number. + * + * @param number The field number to look up. + * + * @return The GPBUnknownField or nil if none found. + **/ +- (nullable GPBUnknownField *)getField:(int32_t)number; + +/** + * @return The number of fields in this set. + **/ +- (NSUInteger)countOfFields; + +/** + * Adds the given field to the set. + * + * @param field The field to add to the set. + **/ +- (void)addField:(GPBUnknownField *)field; + +/** + * @return An array of the GPBUnknownFields sorted by the field numbers. + **/ +- (NSArray *)sortedFields; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.m new file mode 100644 index 0000000..a7335f0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet.m @@ -0,0 +1,395 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBUnknownFieldSet_PackagePrivate.h" + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" +#import "GPBUnknownField_PackagePrivate.h" +#import "GPBUtilities.h" +#import "GPBWireFormat.h" + +#pragma mark Helpers + +static void checkNumber(int32_t number) { + if (number == 0) { + [NSException raise:NSInvalidArgumentException + format:@"Zero is not a valid field number."]; + } +} + +@implementation GPBUnknownFieldSet { + @package + CFMutableDictionaryRef fields_; +} + +static void CopyWorker(const void *key, const void *value, void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + GPBUnknownFieldSet *result = context; + + GPBUnknownField *copied = [field copy]; + [result addField:copied]; + [copied release]; +} + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +- (id)copyWithZone:(NSZone *)zone { + GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; + if (fields_) { + CFDictionaryApplyFunction(fields_, CopyWorker, result); + } + return result; +} + +- (void)dealloc { + if (fields_) { + CFRelease(fields_); + } + [super dealloc]; +} + +- (BOOL)isEqual:(id)object { + BOOL equal = NO; + if ([object isKindOfClass:[GPBUnknownFieldSet class]]) { + GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object; + if ((fields_ == NULL) && (set->fields_ == NULL)) { + equal = YES; + } else if ((fields_ != NULL) && (set->fields_ != NULL)) { + equal = CFEqual(fields_, set->fields_); + } + } + return equal; +} + +- (NSUInteger)hash { + // Return the hash of the fields dictionary (or just some value). + if (fields_) { + return CFHash(fields_); + } + return (NSUInteger)[GPBUnknownFieldSet class]; +} + +#pragma mark - Public Methods + +- (BOOL)hasField:(int32_t)number { + ssize_t key = number; + return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; +} + +- (GPBUnknownField *)getField:(int32_t)number { + ssize_t key = number; + GPBUnknownField *result = + fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; + return result; +} + +- (NSUInteger)countOfFields { + return fields_ ? CFDictionaryGetCount(fields_) : 0; +} + +- (NSArray *)sortedFields { + if (!fields_) return [NSArray array]; + size_t count = CFDictionaryGetCount(fields_); + ssize_t keys[count]; + GPBUnknownField *values[count]; + CFDictionaryGetKeysAndValues(fields_, (const void **)keys, + (const void **)values); + struct GPBFieldPair { + ssize_t key; + GPBUnknownField *value; + } pairs[count]; + for (size_t i = 0; i < count; ++i) { + pairs[i].key = keys[i]; + pairs[i].value = values[i]; + }; + qsort_b(pairs, count, sizeof(struct GPBFieldPair), + ^(const void *first, const void *second) { + const struct GPBFieldPair *a = first; + const struct GPBFieldPair *b = second; + return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); + }); + for (size_t i = 0; i < count; ++i) { + values[i] = pairs[i].value; + }; + return [NSArray arrayWithObjects:values count:count]; +} + +#pragma mark - Internal Methods + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { + if (!fields_) return; + size_t count = CFDictionaryGetCount(fields_); + ssize_t keys[count]; + GPBUnknownField *values[count]; + CFDictionaryGetKeysAndValues(fields_, (const void **)keys, + (const void **)values); + if (count > 1) { + struct GPBFieldPair { + ssize_t key; + GPBUnknownField *value; + } pairs[count]; + + for (size_t i = 0; i < count; ++i) { + pairs[i].key = keys[i]; + pairs[i].value = values[i]; + }; + qsort_b(pairs, count, sizeof(struct GPBFieldPair), + ^(const void *first, const void *second) { + const struct GPBFieldPair *a = first; + const struct GPBFieldPair *b = second; + return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); + }); + for (size_t i = 0; i < count; ++i) { + GPBUnknownField *value = pairs[i].value; + [value writeToOutput:output]; + } + } else { + [values[0] writeToOutput:output]; + } +} + +- (NSString *)description { + NSMutableString *description = [NSMutableString + stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self]; + NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" "); + [description appendString:textFormat]; + [description appendString:@"}"]; + return description; +} + +static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + size_t *result = context; + *result += [field serializedSize]; +} + +- (size_t)serializedSize { + size_t result = 0; + if (fields_) { + CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize, + &result); + } + return result; +} + +static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key, + const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + GPBCodedOutputStream *output = context; + [field writeAsMessageSetExtensionToOutput:output]; +} + +- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output { + if (fields_) { + CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo, + output); + } +} + +static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, + const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + size_t *result = context; + *result += [field serializedSizeAsMessageSetExtension]; +} + +- (size_t)serializedSizeAsMessageSet { + size_t result = 0; + if (fields_) { + CFDictionaryApplyFunction( + fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result); + } + return result; +} + +- (NSData *)data { + NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize]; + GPBCodedOutputStream *output = + [[GPBCodedOutputStream alloc] initWithData:data]; + [self writeToCodedOutputStream:output]; + [output release]; + return data; +} + ++ (BOOL)isFieldTag:(int32_t)tag { + return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; +} + +- (void)addField:(GPBUnknownField *)field { + int32_t number = [field number]; + checkNumber(number); + if (!fields_) { + // Use a custom dictionary here because the keys are numbers and conversion + // back and forth from NSNumber isn't worth the cost. + fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, + &kCFTypeDictionaryValueCallBacks); + } + ssize_t key = number; + CFDictionarySetValue(fields_, (const void *)key, field); +} + +- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { + ssize_t key = number; + GPBUnknownField *existing = + fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; + if (!existing && create) { + existing = [[GPBUnknownField alloc] initWithNumber:number]; + // This retains existing. + [self addField:existing]; + [existing release]; + } + return existing; +} + +static void GPBUnknownFieldSetMergeUnknownFields(const void *key, + const void *value, + void *context) { +#pragma unused(key) + GPBUnknownField *field = value; + GPBUnknownFieldSet *self = context; + + int32_t number = [field number]; + checkNumber(number); + GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO]; + if (oldField) { + [oldField mergeFromField:field]; + } else { + // Merge only comes from GPBMessage's mergeFrom:, so it means we are on + // mutable message and are an mutable instance, so make sure we need + // mutable fields. + GPBUnknownField *fieldCopy = [field copy]; + [self addField:fieldCopy]; + [fieldCopy release]; + } +} + +- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other { + if (other && other->fields_) { + CFDictionaryApplyFunction(other->fields_, + GPBUnknownFieldSetMergeUnknownFields, self); + } +} + +- (void)mergeFromData:(NSData *)data { + GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; + [self mergeFromCodedInputStream:input]; + [input checkLastTagWas:0]; + [input release]; +} + +- (void)mergeVarintField:(int32_t)number value:(int32_t)value { + checkNumber(number); + [[self mutableFieldForNumber:number create:YES] addVarint:value]; +} + +- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { + NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag"); + int32_t number = GPBWireFormatGetTagFieldNumber(tag); + GPBCodedInputStreamState *state = &input->state_; + switch (GPBWireFormatGetTagWireType(tag)) { + case GPBWireFormatVarint: { + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addVarint:GPBCodedInputStreamReadInt64(state)]; + return YES; + } + case GPBWireFormatFixed64: { + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addFixed64:GPBCodedInputStreamReadFixed64(state)]; + return YES; + } + case GPBWireFormatLengthDelimited: { + NSData *data = GPBCodedInputStreamReadRetainedBytes(state); + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addLengthDelimited:data]; + [data release]; + return YES; + } + case GPBWireFormatStartGroup: { + GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; + [input readUnknownGroup:number message:unknownFieldSet]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addGroup:unknownFieldSet]; + [unknownFieldSet release]; + return YES; + } + case GPBWireFormatEndGroup: + return NO; + case GPBWireFormatFixed32: { + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; + [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; + return YES; + } + } +} + +- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData { + [[self mutableFieldForNumber:number create:YES] + addLengthDelimited:messageData]; +} + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { + GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; + [field addLengthDelimited:data]; +} + +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input { + while (YES) { + int32_t tag = GPBCodedInputStreamReadTag(&input->state_); + if (tag == 0 || ![self mergeFieldFrom:tag input:input]) { + break; + } + } +} + +- (void)getTags:(int32_t *)tags { + if (!fields_) return; + size_t count = CFDictionaryGetCount(fields_); + ssize_t keys[count]; + CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); + for (size_t i = 0; i < count; ++i) { + tags[i] = (int32_t)keys[i]; + } +} + +#pragma clang diagnostic pop + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet_PackagePrivate.h new file mode 100644 index 0000000..e27127a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownFieldSet_PackagePrivate.h @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBUnknownFieldSet.h" + +@class GPBCodedOutputStream; +@class GPBCodedInputStream; + +@interface GPBUnknownFieldSet () + ++ (BOOL)isFieldTag:(int32_t)tag; + +- (NSData *)data; + +- (size_t)serializedSize; +- (size_t)serializedSizeAsMessageSet; + +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output; +- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output; + +- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other; + +- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input; +- (void)mergeFromData:(NSData *)data; + +- (void)mergeVarintField:(int32_t)number value:(int32_t)value; +- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input; +- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData; + +- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField_PackagePrivate.h new file mode 100644 index 0000000..2b4c789 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUnknownField_PackagePrivate.h @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBUnknownField.h" + +@class GPBCodedOutputStream; + +@interface GPBUnknownField () + +- (void)writeToOutput:(GPBCodedOutputStream *)output; +- (size_t)serializedSize; + +- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output; +- (size_t)serializedSizeAsMessageSetExtension; + +- (void)mergeFromField:(GPBUnknownField *)other; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities.h new file mode 100644 index 0000000..5464dfb --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities.h @@ -0,0 +1,539 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBArray.h" +#import "GPBMessage.h" +#import "GPBRuntimeTypes.h" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +/** + * Generates a string that should be a valid "TextFormat" for the C++ version + * of Protocol Buffers. + * + * @param message The message to generate from. + * @param lineIndent A string to use as the prefix for all lines generated. Can + * be nil if no extra indent is needed. + * + * @return An NSString with the TextFormat of the message. + **/ +NSString *GPBTextFormatForMessage(GPBMessage *message, + NSString * __nullable lineIndent); + +/** + * Generates a string that should be a valid "TextFormat" for the C++ version + * of Protocol Buffers. + * + * @param unknownSet The unknown field set to generate from. + * @param lineIndent A string to use as the prefix for all lines generated. Can + * be nil if no extra indent is needed. + * + * @return An NSString with the TextFormat of the unknown field set. + **/ +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet * __nullable unknownSet, + NSString * __nullable lineIndent); + +/** + * Checks if the given field number is set on a message. + * + * @param self The message to check. + * @param fieldNumber The field number to check. + * + * @return YES if the field number is set on the given message. + **/ +BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber); + +/** + * Checks if the given field is set on a message. + * + * @param self The message to check. + * @param field The field to check. + * + * @return YES if the field is set on the given message. + **/ +BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Clears the given field for the given message. + * + * @param self The message for which to clear the field. + * @param field The field to clear. + **/ +void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); + +//%PDDM-EXPAND GPB_ACCESSORS() +// This block of code is generated, do not edit it directly. + + +// +// Get/Set a given field from/to a message. +// + +// Single Fields + +/** + * Gets the value of a bytes field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a bytes field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value); + +/** + * Gets the value of a string field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a string field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value); + +/** + * Gets the value of a message field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a message field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +/** + * Gets the value of a group field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a group field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +/** + * Gets the value of a bool field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a bool field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value); + +/** + * Gets the value of an int32 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an int32 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); + +/** + * Gets the value of an uint32 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an uint32 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value); + +/** + * Gets the value of an int64 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an int64 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value); + +/** + * Gets the value of an uint64 field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of an uint64 field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value); + +/** + * Gets the value of a float field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a float field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value); + +/** + * Gets the value of a double field. + * + * @param self The message from which to get the field. + * @param field The field to get. + **/ +double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a double field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The to set in the field. + **/ +void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value); + +/** + * Gets the given enum field of a message. For proto3, if the value isn't a + * member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned. + * GPBGetMessageRawEnumField will bypass the check and return whatever value + * was set. + * + * @param self The message from which to get the field. + * @param field The field to get. + * + * @return The enum value for the given field. + **/ +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Set the given enum field of a message. You can only set values that are + * members of the enum. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The enum value to set in the field. + **/ +void GPBSetMessageEnumField(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); + +/** + * Get the given enum field of a message. No check is done to ensure the value + * was defined in the enum. + * + * @param self The message from which to get the field. + * @param field The field to get. + * + * @return The raw enum value for the given field. + **/ +int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Set the given enum field of a message. You can set the value to anything, + * even a value that is not a member of the enum. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param value The raw enum value to set in the field. + **/ +void GPBSetMessageRawEnumField(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); + +// Repeated Fields + +/** + * Gets the value of a repeated field. + * + * @param self The message from which to get the field. + * @param field The repeated field to get. + * + * @return A GPB*Array or an NSMutableArray based on the field's type. + **/ +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a repeated field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param array A GPB*Array or NSMutableArray based on the field's type. + **/ +void GPBSetMessageRepeatedField(GPBMessage *self, + GPBFieldDescriptor *field, + id array); + +// Map Fields + +/** + * Gets the value of a map<> field. + * + * @param self The message from which to get the field. + * @param field The repeated field to get. + * + * @return A GPB*Dictionary or NSMutableDictionary based on the field's type. + **/ +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); + +/** + * Sets the value of a map<> field. + * + * @param self The message into which to set the field. + * @param field The field to set. + * @param dictionary A GPB*Dictionary or NSMutableDictionary based on the + * field's type. + **/ +void GPBSetMessageMapField(GPBMessage *self, + GPBFieldDescriptor *field, + id dictionary); + +//%PDDM-EXPAND-END GPB_ACCESSORS() + +/** + * Returns an empty NSData to assign to byte fields when you wish to assign them + * to empty. Prevents allocating a lot of little [NSData data] objects. + **/ +NSData *GPBEmptyNSData(void) __attribute__((pure)); + +/** + * Drops the `unknownFields` from the given message and from all sub message. + **/ +void GPBMessageDropUnknownFieldsRecursively(GPBMessage *message); + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + + +//%PDDM-DEFINE GPB_ACCESSORS() +//% +//%// +//%// Get/Set a given field from/to a message. +//%// +//% +//%// Single Fields +//% +//%GPB_ACCESSOR_SINGLE_FULL(Bytes, NSData, , *) +//%GPB_ACCESSOR_SINGLE_FULL(String, NSString, , *) +//%GPB_ACCESSOR_SINGLE_FULL(Message, GPBMessage, , *) +//%GPB_ACCESSOR_SINGLE_FULL(Group, GPBMessage, , *) +//%GPB_ACCESSOR_SINGLE(Bool, BOOL, ) +//%GPB_ACCESSOR_SINGLE(Int32, int32_t, n) +//%GPB_ACCESSOR_SINGLE(UInt32, uint32_t, n) +//%GPB_ACCESSOR_SINGLE(Int64, int64_t, n) +//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t, n) +//%GPB_ACCESSOR_SINGLE(Float, float, ) +//%GPB_ACCESSOR_SINGLE(Double, double, ) +//%/** +//% * Gets the given enum field of a message. For proto3, if the value isn't a +//% * member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned. +//% * GPBGetMessageRawEnumField will bypass the check and return whatever value +//% * was set. +//% * +//% * @param self The message from which to get the field. +//% * @param field The field to get. +//% * +//% * @return The enum value for the given field. +//% **/ +//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Set the given enum field of a message. You can only set values that are +//% * members of the enum. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param value The enum value to set in the field. +//% **/ +//%void GPBSetMessageEnumField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% int32_t value); +//% +//%/** +//% * Get the given enum field of a message. No check is done to ensure the value +//% * was defined in the enum. +//% * +//% * @param self The message from which to get the field. +//% * @param field The field to get. +//% * +//% * @return The raw enum value for the given field. +//% **/ +//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Set the given enum field of a message. You can set the value to anything, +//% * even a value that is not a member of the enum. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param value The raw enum value to set in the field. +//% **/ +//%void GPBSetMessageRawEnumField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% int32_t value); +//% +//%// Repeated Fields +//% +//%/** +//% * Gets the value of a repeated field. +//% * +//% * @param self The message from which to get the field. +//% * @param field The repeated field to get. +//% * +//% * @return A GPB*Array or an NSMutableArray based on the field's type. +//% **/ +//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Sets the value of a repeated field. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param array A GPB*Array or NSMutableArray based on the field's type. +//% **/ +//%void GPBSetMessageRepeatedField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% id array); +//% +//%// Map Fields +//% +//%/** +//% * Gets the value of a map<> field. +//% * +//% * @param self The message from which to get the field. +//% * @param field The repeated field to get. +//% * +//% * @return A GPB*Dictionary or NSMutableDictionary based on the field's type. +//% **/ +//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Sets the value of a map<> field. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param dictionary A GPB*Dictionary or NSMutableDictionary based on the +//% * field's type. +//% **/ +//%void GPBSetMessageMapField(GPBMessage *self, +//% GPBFieldDescriptor *field, +//% id dictionary); +//% + +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE, AN) +//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, ) +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, TisP) +//%/** +//% * Gets the value of a##AN NAME$L field. +//% * +//% * @param self The message from which to get the field. +//% * @param field The field to get. +//% **/ +//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field); +//% +//%/** +//% * Sets the value of a##AN NAME$L field. +//% * +//% * @param self The message into which to set the field. +//% * @param field The field to set. +//% * @param value The to set in the field. +//% **/ +//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value); +//% diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities.m new file mode 100644 index 0000000..0d3a080 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities.m @@ -0,0 +1,2214 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBUtilities_PackagePrivate.h" + +#import + +#import "GPBArray_PackagePrivate.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFieldSet.h" + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +static void AppendTextFormatForMessage(GPBMessage *message, + NSMutableString *toStr, + NSString *lineIndent); + +// Are two datatypes the same basic type representation (ex Int32 and SInt32). +// Marked unused because currently only called from asserts/debug. +static BOOL DataTypesEquivalent(GPBDataType type1, + GPBDataType type2) __attribute__ ((unused)); + +// Basic type representation for a type (ex: for SInt32 it is Int32). +// Marked unused because currently only called from asserts/debug. +static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused)); + +// String name for a data type. +// Marked unused because currently only called from asserts/debug. +static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused)); + +NSData *GPBEmptyNSData(void) { + static dispatch_once_t onceToken; + static NSData *defaultNSData = nil; + dispatch_once(&onceToken, ^{ + defaultNSData = [[NSData alloc] init]; + }); + return defaultNSData; +} + +void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) { + if (!initialMessage) { + return; + } + + // Use an array as a list to process to avoid recursion. + NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage]; + + while (todo.count) { + GPBMessage *msg = todo.lastObject; + [todo removeLastObject]; + + // Clear unknowns. + msg.unknownFields = nil; + + // Handle the message fields. + GPBDescriptor *descriptor = [[msg class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (!GPBFieldDataTypeIsMessage(field)) { + continue; + } + switch (field.fieldType) { + case GPBFieldTypeSingle: + if (GPBGetHasIvarField(msg, field)) { + GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); + [todo addObject:fieldMessage]; + } + break; + + case GPBFieldTypeRepeated: { + NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); + if (fieldMessages.count) { + [todo addObjectsFromArray:fieldMessages]; + } + break; + } + + case GPBFieldTypeMap: { + id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); + switch (field.mapKeyDataType) { + case GPBDataTypeBool: + [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + BOOL key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + int32_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + int64_t key, id _Nonnull object, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:object]; + }]; + break; + case GPBDataTypeString: + [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( + NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) { + #pragma unused(key, stop) + [todo addObject:obj]; + }]; + break; + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeEnum: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + NSCAssert(NO, @"Aren't valid key types."); + } + break; + } // switch(field.mapKeyDataType) + } // switch(field.fieldType) + } // for(fields) + + // Handle any extensions holding messages. + for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) { + if (!GPBDataTypeIsMessage(extension.dataType)) { + continue; + } + if (extension.isRepeated) { + NSArray *extMessages = [msg getExtension:extension]; + [todo addObjectsFromArray:extMessages]; + } else { + GPBMessage *extMessage = [msg getExtension:extension]; + [todo addObject:extMessage]; + } + } // for(extensionsCurrentlySet) + + } // while(todo.count) +} + + +// -- About Version Checks -- +// There's actually 3 places these checks all come into play: +// 1. When the generated source is compile into .o files, the header check +// happens. This is checking the protoc used matches the library being used +// when making the .o. +// 2. Every place a generated proto header is included in a developer's code, +// the header check comes into play again. But this time it is checking that +// the current library headers being used still support/match the ones for +// the generated code. +// 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is +// called from the generated code passing in values captured when the +// generated code's .o was made. This checks that at runtime the generated +// code and runtime library match. + +void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) { + // NOTE: This is passing the value captured in the compiled code to check + // against the values captured when the runtime support was compiled. This + // ensures the library code isn't in a different framework/library that + // was generated with a non matching version. + if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) { + // Library is too old for headers. + [NSException raise:NSInternalInconsistencyException + format:@"Linked to ProtocolBuffer runtime version %d," + @" but code compiled needing atleast %d!", + GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion]; + } + if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { + // Headers are too old for library. + [NSException raise:NSInternalInconsistencyException + format:@"Proto generation source compiled against runtime" + @" version %d, but this version of the runtime only" + @" supports back to %d!", + objcRuntimeVersion, + GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION]; + } +} + +// This api is no longer used for version checks. 30001 is the last version +// using this old versioning model. When that support is removed, this function +// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h). +void GPBCheckRuntimeVersionInternal(int32_t version) { + GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001, + time_to_remove_this_old_version_shim); + if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { + [NSException raise:NSInternalInconsistencyException + format:@"Linked to ProtocolBuffer runtime version %d," + @" but code compiled with version %d!", + GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; + } +} + +BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { + GPBDescriptor *descriptor = [self descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; + return GPBMessageHasFieldSet(self, field); +} + +BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) { + if (self == nil || field == nil) return NO; + + // Repeated/Map don't use the bit, they check the count. + if (GPBFieldIsMapOrArray(field)) { + // Array/map type doesn't matter, since GPB*Array/NSArray and + // GPB*Dictionary/NSDictionary all support -count; + NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + return (arrayOrMap.count > 0); + } else { + return GPBGetHasIvarField(self, field); + } +} + +void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { + // If not set, nothing to do. + if (!GPBGetHasIvarField(self, field)) { + return; + } + + if (GPBFieldStoresObject(field)) { + // Object types are handled slightly differently, they need to be released. + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + [*typePtr release]; + *typePtr = nil; + } else { + // POD types just need to clear the has bit as the Get* method will + // fetch the default when needed. + } + GPBSetHasIvarField(self, field, NO); +} + +BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); + if (idx < 0) { + NSCAssert(fieldNumber != 0, @"Invalid field number."); + BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber); + return hasIvar; + } else { + NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); + uint32_t byteIndex = idx / 32; + uint32_t bitMask = (1U << (idx % 32)); + BOOL hasIvar = + (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO; + return hasIvar; + } +} + +uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) { + NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", + [self class], idx); + uint32_t result = self->messageStorage_->_has_storage_[-idx]; + return result; +} + +void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, + BOOL value) { + if (idx < 0) { + NSCAssert(fieldNumber != 0, @"Invalid field number."); + uint32_t *has_storage = self->messageStorage_->_has_storage_; + has_storage[-idx] = (value ? fieldNumber : 0); + } else { + NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); + uint32_t *has_storage = self->messageStorage_->_has_storage_; + uint32_t byte = idx / 32; + uint32_t bitMask = (1U << (idx % 32)); + if (value) { + has_storage[byte] |= bitMask; + } else { + has_storage[byte] &= ~bitMask; + } + } +} + +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { + uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); + if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { + // Do nothing/nothing set in the oneof. + return; + } + + // Like GPBClearMessageField(), free the memory if an objecttype is set, + // pod types don't need to do anything. + GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet]; + NSCAssert(fieldSet, + @"%@: oneof set to something (%u) not in the oneof?", + [self class], fieldNumberSet); + if (fieldSet && GPBFieldStoresObject(fieldSet)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[fieldSet->description_->offset]; + [*typePtr release]; + *typePtr = nil; + } + + // Set to nothing stored in the oneof. + // (field number doesn't matter since setting to nothing). + GPBSetHasIvar(self, oneofHasIndex, 1, NO); +} + +#pragma mark - IVar accessors + +//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) +//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% if (GPBGetHasIvarField(self, field)) { +//% uint8_t *storage = (uint8_t *)self->messageStorage_; +//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; +//% return *typePtr; +//% } else { +//% return field.defaultValue.value##NAME; +//% } +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value) { +//% if (self == nil || field == nil) return; +//% GPBFileSyntax syntax = [self descriptor].file.syntax; +//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); +//%} +//% +//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value, +//% NAME$S GPBFileSyntax syntax) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBOneofDescriptor *oneof = field->containingOneof_; +//% if (oneof) { +//% GPBMessageFieldDescription *fieldDesc = field->description_; +//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); +//% } +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(self->messageStorage_ != NULL, +//% @"%@: All messages should have storage (from init)", +//% [self class]); +//%#endif +//%#if defined(__clang_analyzer__) +//% if (self->messageStorage_ == NULL) return; +//%#endif +//% uint8_t *storage = (uint8_t *)self->messageStorage_; +//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; +//% *typePtr = value; +//% // proto2: any value counts as having been set; proto3, it +//% // has to be a non zero value or be in a oneof. +//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2) +//% || (value != (TYPE)0) +//% || (field->containingOneof_ != NULL)); +//% GPBSetHasIvarField(self, field, hasValue); +//% GPBBecomeVisibleToAutocreator(self); +//%} +//% +//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE) +//%// Only exists for public api, no core code should use this. +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% return (TYPE *)GPBGetObjectIvarWithField(self, field); +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBSetObjectIvarWithField(self, field, (id)value); +//%} +//% +//%PDDM-DEFINE IVAR_ALIAS_DEFN_COPY_OBJECT(NAME, TYPE) +//%// Only exists for public api, no core code should use this. +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% return (TYPE *)GPBGetObjectIvarWithField(self, field); +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBSetCopyObjectIvarWithField(self, field, (id)value); +//%} +//% + +// Object types are handled slightly differently, they need to be released +// and retained. + +void GPBSetAutocreatedRetainedObjectIvarWithField( + GPBMessage *self, GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) value) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once."); + *typePtr = value; +} + +void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field) { + if (GPBGetHasIvarField(self, field)) { + return; + } + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + GPBMessage *oldValue = *typePtr; + *typePtr = NULL; + GPBClearMessageAutocreator(oldValue); + [oldValue release]; +} + +// This exists only for briging some aliased types, nothing else should use it. +static void GPBSetObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], + syntax); +} + +static void GPBSetCopyObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value); + +// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags +// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldInternal +// is marked as consuming the value. Note: For some reason this doesn't happen +// with the -retain in GPBSetObjectIvarWithField. +#if !defined(__clang_analyzer__) +// This exists only for briging some aliased types, nothing else should use it. +static void GPBSetCopyObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value copy], + syntax); +} +#endif // !defined(__clang_analyzer__) + +void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, id value, + GPBFileSyntax syntax) { + GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], + syntax); +} + +void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + id value, GPBFileSyntax syntax) { + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + GPBDataType fieldType = GPBGetFieldDataType(field); + BOOL isMapOrArray = GPBFieldIsMapOrArray(field); + BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); +#if defined(DEBUG) && DEBUG + if (value == nil && !isMapOrArray && !fieldIsMessage && + field.hasDefaultValue) { + // Setting a message to nil is an obvious way to "clear" the value + // as there is no way to set a non-empty default value for messages. + // + // For Strings and Bytes that have default values set it is not clear what + // should be done when their value is set to nil. Is the intention just to + // clear the set value and reset to default, or is the intention to set the + // value to the empty string/data? Arguments can be made for both cases. + // 'nil' has been abused as a replacement for an empty string/data in ObjC. + // We decided to be consistent with all "object" types and clear the has + // field, and fall back on the default value. The warning below will only + // appear in debug, but the could should be changed so the intention is + // clear. + NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_); + NSString *propName = field.name; + NSString *className = self.descriptor.name; + NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with " + @"default values. Please use '%@.%@ = %@' if you want to set it to " + @"empty, or call '%@.%@ = NO' to reset it to it's default value of " + @"'%@'. Defaulting to resetting default value.", + className, propName, className, propName, + (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", + className, hasSel, field.defaultValue.valueString); + // Note: valueString, depending on the type, it could easily be + // valueData/valueMessage. + } +#endif // DEBUG + if (!isMapOrArray) { + // Non repeated/map can be in an oneof, clear any existing value from the + // oneof. + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } + // Clear "has" if they are being set to nil. + BOOL setHasValue = (value != nil); + // Under proto3, Bytes & String fields get cleared by resetting them to + // their default (empty) values, so if they are set to something of length + // zero, they are being cleared. + if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && + ([value length] == 0)) { + // Except, if the field was in a oneof, then it still gets recorded as + // having been set so the state of the oneof can be serialized back out. + if (!oneof) { + setHasValue = NO; + } + if (setHasValue) { + NSCAssert(value != nil, @"Should never be setting has for nil"); + } else { + // The value passed in was retained, it must be released since we + // aren't saving anything in the field. + [value release]; + value = nil; + } + } + GPBSetHasIvarField(self, field, setHasValue); + } + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + + id oldValue = *typePtr; + + *typePtr = value; + + if (oldValue) { + if (isMapOrArray) { + if (field.fieldType == GPBFieldTypeRepeated) { + // If the old array was autocreated by us, then clear it. + if (GPBDataTypeIsObject(fieldType)) { + if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) { + GPBAutocreatedArray *autoArray = oldValue; + if (autoArray->_autocreator == self) { + autoArray->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Array. + GPBInt32Array *gpbArray = oldValue; + if (gpbArray->_autocreator == self) { + gpbArray->_autocreator = nil; + } + } + } else { // GPBFieldTypeMap + // If the old map was autocreated by us, then clear it. + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(fieldType)) { + if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) { + GPBAutocreatedDictionary *autoDict = oldValue; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } + } + } else { + // Type doesn't matter, it is a GPB*Dictionary. + GPBInt32Int32Dictionary *gpbDict = oldValue; + if (gpbDict->_autocreator == self) { + gpbDict->_autocreator = nil; + } + } + } + } else if (fieldIsMessage) { + // If the old message value was autocreated by us, then clear it. + GPBMessage *oldMessageValue = oldValue; + if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) { + GPBClearMessageAutocreator(oldMessageValue); + } + } + [oldValue release]; + } + + GPBBecomeVisibleToAutocreator(self); +} + +id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, + GPBFieldDescriptor *field) { + if (self->messageStorage_ == nil) { + return nil; + } + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + return *typePtr; +} + +// Only exists for public api, no core code should use this. +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + return GPBGetEnumIvarWithFieldInternal(self, field, syntax); +} + +int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to get value of type Enum from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + int32_t result = GPBGetMessageInt32Field(self, field); + // If this is presevering unknown enums, make sure the value is valid before + // returning it. + if (GPBHasPreservingUnknownEnumSemantics(syntax) && + ![field isValidEnumValue:result]) { + result = kGPBUnrecognizedEnumeratorValue; + } + return result; +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, int32_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type Enum.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + // Don't allow in unknown values. Proto3 can use the Raw method. + if (![field isValidEnumValue:value]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Attempt to set an unknown enum value (%d)", + [self class], field.name, value]; + } + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +// Only exists for public api, no core code should use this. +int32_t GPBGetMessageRawEnumField(GPBMessage *self, + GPBFieldDescriptor *field) { + int32_t result = GPBGetMessageInt32Field(self, field); + return result; +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +BOOL GPBGetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to get value of type bool from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + // Bools are stored in the has bits to avoid needing explicit space in the + // storage structure. + // (the field number passed to the HasIvar helper doesn't really matter + // since the offset is never negative) + GPBMessageFieldDescription *fieldDesc = field->description_; + return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number); + } else { + return field.defaultValue.valueBool; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type bool.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } + + // Bools are stored in the has bits to avoid needing explicit space in the + // storage structure. + // (the field number passed to the HasIvar helper doesn't really matter since + // the offset is never negative) + GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value); + + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (BOOL)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +int32_t GPBGetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt32), + @"Attempting to get value of int32_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueInt32; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt32), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type int32_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (int32_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt32), + @"Attempting to get value of uint32_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueUInt32; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt32), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type uint32_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (uint32_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +int64_t GPBGetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt64), + @"Attempting to get value of int64_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueInt64; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt64), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type int64_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (int64_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt64), + @"Attempting to get value of uint64_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueUInt64; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt64), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type uint64_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (uint64_t)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float) +// This block of code is generated, do not edit it directly. + +float GPBGetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeFloat), + @"Attempting to get value of float from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + float *typePtr = (float *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueFloat; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field, + float value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + float value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeFloat), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type float.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + float *typePtr = (float *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (float)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double) +// This block of code is generated, do not edit it directly. + +double GPBGetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeDouble), + @"Attempting to get value of double from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + double *typePtr = (double *)&storage[field->description_->offset]; + return *typePtr; + } else { + return field.defaultValue.valueDouble; + } +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field, + double value) { + if (self == nil || field == nil) return; + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + double value, + GPBFileSyntax syntax) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeDouble), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type double.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBOneofDescriptor *oneof = field->containingOneof_; + if (oneof) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + } +#if defined(DEBUG) && DEBUG + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); +#endif +#if defined(__clang_analyzer__) + if (self->messageStorage_ == NULL) return; +#endif + uint8_t *storage = (uint8_t *)self->messageStorage_; + double *typePtr = (double *)&storage[field->description_->offset]; + *typePtr = value; + // proto2: any value counts as having been set; proto3, it + // has to be a non zero value or be in a oneof. + BOOL hasValue = ((syntax == GPBFileSyntaxProto2) + || (value != (double)0) + || (field->containingOneof_ != NULL)); + GPBSetHasIvarField(self, field, hasValue); + GPBBecomeVisibleToAutocreator(self); +} + +//%PDDM-EXPAND-END (6 expansions) + +// Aliases are function calls that are virtually the same. + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +NSString *GPBGetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeString), + @"Attempting to get value of NSString from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (NSString *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field, + NSString *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeString), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type NSString.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetCopyObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +NSData *GPBGetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeBytes), + @"Attempting to get value of NSData from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (NSData *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field, + NSData *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeBytes), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type NSData.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetCopyObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeMessage), + @"Attempting to get value of GPBMessage from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageMessageField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBMessage *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeMessage), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type GPBMessage.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) +// This block of code is generated, do not edit it directly. + +// Only exists for public api, no core code should use this. +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, + GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeGroup), + @"Attempting to get value of GPBMessage from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageGroupField(GPBMessage *self, + GPBFieldDescriptor *field, + GPBMessage *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeGroup), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type GPBMessage.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetObjectIvarWithField(self, field, (id)value); +} + +//%PDDM-EXPAND-END (4 expansions) + +// GPBGetMessageRepeatedField is defined in GPBMessage.m + +// Only exists for public api, no core code should use this. +void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } + Class expectedClass = Nil; + switch (GPBGetFieldDataType(field)) { + case GPBDataTypeBool: + expectedClass = [GPBBoolArray class]; + break; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + expectedClass = [GPBInt32Array class]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + expectedClass = [GPBUInt32Array class]; + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + expectedClass = [GPBInt64Array class]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + expectedClass = [GPBUInt64Array class]; + break; + case GPBDataTypeFloat: + expectedClass = [GPBFloatArray class]; + break; + case GPBDataTypeDouble: + expectedClass = [GPBDoubleArray class]; + break; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + expectedClass = [NSMutableArray class]; + break; + case GPBDataTypeEnum: + expectedClass = [GPBEnumArray class]; + break; + } + if (array && ![array isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, [array class]]; + } +#endif + GPBSetObjectIvarWithField(self, field, array); +} + +static GPBDataType BaseDataType(GPBDataType type) { + switch (type) { + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + return GPBDataTypeInt32; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return GPBDataTypeUInt32; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return GPBDataTypeInt64; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return GPBDataTypeUInt64; + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return GPBDataTypeMessage; + case GPBDataTypeBool: + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeBytes: + case GPBDataTypeString: + return type; + } +} + +static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) { + return BaseDataType(type1) == BaseDataType(type2); +} + +static NSString *TypeToString(GPBDataType dataType) { + switch (dataType) { + case GPBDataTypeBool: + return @"Bool"; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + return @"Int32"; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return @"UInt32"; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return @"Int64"; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return @"UInt64"; + case GPBDataTypeFloat: + return @"Float"; + case GPBDataTypeDouble: + return @"Double"; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return @"Object"; + case GPBDataTypeEnum: + return @"Enum"; + } +} + +// GPBGetMessageMapField is defined in GPBMessage.m + +// Only exists for public api, no core code should use this. +void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, + id dictionary) { +#if defined(DEBUG) && DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } + if (dictionary) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSString *keyStr = TypeToString(keyDataType); + NSString *valueStr = TypeToString(valueDataType); + if (keyDataType == GPBDataTypeString) { + keyStr = @"String"; + } + Class expectedClass = Nil; + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + expectedClass = [NSMutableDictionary class]; + } else { + NSString *className = + [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr]; + expectedClass = NSClassFromString(className); + NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass); + } + if (![dictionary isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, + [dictionary class]]; + } + } +#endif + GPBSetObjectIvarWithField(self, field, dictionary); +} + +#pragma mark - Misc Dynamic Runtime Utils + +const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { + Protocol *protocol = + objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol)); + NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol"); + struct objc_method_description description = + protocol_getMethodDescription(protocol, selector, NO, instanceSel); + NSCAssert(description.name != Nil && description.types != nil, + @"Missing method for selector %@", NSStringFromSelector(selector)); + return description.types; +} + +#pragma mark - Text Format Support + +static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) { + [destStr appendString:@"\""]; + NSUInteger len = [toPrint length]; + for (NSUInteger i = 0; i < len; ++i) { + unichar aChar = [toPrint characterAtIndex:i]; + switch (aChar) { + case '\n': [destStr appendString:@"\\n"]; break; + case '\r': [destStr appendString:@"\\r"]; break; + case '\t': [destStr appendString:@"\\t"]; break; + case '\"': [destStr appendString:@"\\\""]; break; + case '\'': [destStr appendString:@"\\\'"]; break; + case '\\': [destStr appendString:@"\\\\"]; break; + default: + // This differs slightly from the C++ code in that the C++ doesn't + // generate UTF8; it looks at the string in UTF8, but escapes every + // byte > 0x7E. + if (aChar < 0x20) { + [destStr appendFormat:@"\\%d%d%d", + (aChar / 64), ((aChar % 64) / 8), (aChar % 8)]; + } else { + [destStr appendFormat:@"%C", aChar]; + } + break; + } + } + [destStr appendString:@"\""]; +} + +static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) { + const char *src = (const char *)[buffer bytes]; + size_t srcLen = [buffer length]; + [destStr appendString:@"\""]; + for (const char *srcEnd = src + srcLen; src < srcEnd; src++) { + switch (*src) { + case '\n': [destStr appendString:@"\\n"]; break; + case '\r': [destStr appendString:@"\\r"]; break; + case '\t': [destStr appendString:@"\\t"]; break; + case '\"': [destStr appendString:@"\\\""]; break; + case '\'': [destStr appendString:@"\\\'"]; break; + case '\\': [destStr appendString:@"\\\\"]; break; + default: + if (isprint(*src)) { + [destStr appendFormat:@"%c", *src]; + } else { + // NOTE: doing hex means you have to worry about the letter after + // the hex being another hex char and forcing that to be escaped, so + // use octal to keep it simple. + [destStr appendFormat:@"\\%03o", (uint8_t)(*src)]; + } + break; + } + } + [destStr appendString:@"\""]; +} + +static void AppendTextFormatForMapMessageField( + id map, GPBFieldDescriptor *field, NSMutableString *toStr, + NSString *lineIndent, NSString *fieldName, NSString *lineEnding) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType); + + NSString *msgStartFirst = + [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding]; + NSString *msgStart = + [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName]; + NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent]; + + NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent]; + NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent, + (isMessageValue ? "" : ":")]; + + __block BOOL isFirst = YES; + + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + // map is an NSDictionary. + NSDictionary *dict = map; + [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { + #pragma unused(stop) + [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; + isFirst = NO; + + [toStr appendString:keyLine]; + AppendStringEscaped(key, toStr); + [toStr appendString:@"\n"]; + + [toStr appendString:valueLine]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (valueDataType) { + case GPBDataTypeString: + AppendStringEscaped(value, toStr); + break; + + case GPBDataTypeBytes: + AppendBufferAsString(value, toStr); + break; + + case GPBDataTypeMessage: + [toStr appendString:@"{\n"]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(value, toStr, subIndent); + [toStr appendFormat:@"%@ }", lineIndent]; + break; + + default: + NSCAssert(NO, @"Can't happen"); + break; + } +#pragma clang diagnostic pop + [toStr appendString:@"\n"]; + + [toStr appendString:msgEnd]; + }]; + } else { + // map is one of the GPB*Dictionary classes, type doesn't matter. + GPBInt32Int32Dictionary *dict = map; + [dict enumerateForTextFormat:^(id keyObj, id valueObj) { + [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; + isFirst = NO; + + // Key always is a NSString. + if (keyDataType == GPBDataTypeString) { + [toStr appendString:keyLine]; + AppendStringEscaped(keyObj, toStr); + [toStr appendString:@"\n"]; + } else { + [toStr appendFormat:@"%@%@\n", keyLine, keyObj]; + } + + [toStr appendString:valueLine]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" + switch (valueDataType) { + case GPBDataTypeString: + AppendStringEscaped(valueObj, toStr); + break; + + case GPBDataTypeBytes: + AppendBufferAsString(valueObj, toStr); + break; + + case GPBDataTypeMessage: + [toStr appendString:@"{\n"]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(valueObj, toStr, subIndent); + [toStr appendFormat:@"%@ }", lineIndent]; + break; + + case GPBDataTypeEnum: { + int32_t enumValue = [valueObj intValue]; + NSString *valueStr = nil; + GPBEnumDescriptor *descriptor = field.enumDescriptor; + if (descriptor) { + valueStr = [descriptor textFormatNameForValue:enumValue]; + } + if (valueStr) { + [toStr appendString:valueStr]; + } else { + [toStr appendFormat:@"%d", enumValue]; + } + break; + } + + default: + NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen"); + // Everything else is a NSString. + [toStr appendString:valueObj]; + break; + } +#pragma clang diagnostic pop + [toStr appendString:@"\n"]; + + [toStr appendString:msgEnd]; + }]; + } +} + +static void AppendTextFormatForMessageField(GPBMessage *message, + GPBFieldDescriptor *field, + NSMutableString *toStr, + NSString *lineIndent) { + id arrayOrMap; + NSUInteger count; + GPBFieldType fieldType = field.fieldType; + switch (fieldType) { + case GPBFieldTypeSingle: + arrayOrMap = nil; + count = (GPBGetHasIvarField(message, field) ? 1 : 0); + break; + + case GPBFieldTypeRepeated: + // Will be NSArray or GPB*Array, type doesn't matter, they both + // implement count. + arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); + count = [(NSArray *)arrayOrMap count]; + break; + + case GPBFieldTypeMap: { + // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter, + // they both implement count. + arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); + count = [(NSDictionary *)arrayOrMap count]; + break; + } + } + + if (count == 0) { + // Nothing to print, out of here. + return; + } + + NSString *lineEnding = @""; + + // If the name can't be reversed or support for extra info was turned off, + // this can return nil. + NSString *fieldName = [field textFormatName]; + if ([fieldName length] == 0) { + fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)]; + // If there is only one entry, put the objc name as a comment, other wise + // add it before the repeated values. + if (count > 1) { + [toStr appendFormat:@"%@# %@\n", lineIndent, field.name]; + } else { + lineEnding = [NSString stringWithFormat:@" # %@", field.name]; + } + } + + if (fieldType == GPBFieldTypeMap) { + AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, + fieldName, lineEnding); + return; + } + + id array = arrayOrMap; + const BOOL isRepeated = (array != nil); + + GPBDataType fieldDataType = GPBGetFieldDataType(field); + BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType); + for (NSUInteger j = 0; j < count; ++j) { + // Start the line. + [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, + (isMessageField ? "" : ":")]; + + // The value. + switch (fieldDataType) { +#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \ + : GPBGetMessage##REAL_TYPE##Field(message, field)); \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ + } + + FIELD_CASE(Int32, int32_t, Int32, @"%d") + FIELD_CASE(SInt32, int32_t, Int32, @"%d") + FIELD_CASE(SFixed32, int32_t, Int32, @"%d") + FIELD_CASE(UInt32, uint32_t, UInt32, @"%u") + FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u") + FIELD_CASE(Int64, int64_t, Int64, @"%lld") + FIELD_CASE(SInt64, int64_t, Int64, @"%lld") + FIELD_CASE(SFixed64, int64_t, Int64, @"%lld") + FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu") + FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu") + FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG) + FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG) + +#undef FIELD_CASE + + case GPBDataTypeEnum: { + int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j] + : GPBGetMessageInt32Field(message, field)); + NSString *valueStr = nil; + GPBEnumDescriptor *descriptor = field.enumDescriptor; + if (descriptor) { + valueStr = [descriptor textFormatNameForValue:v]; + } + if (valueStr) { + [toStr appendString:valueStr]; + } else { + [toStr appendFormat:@"%d", v]; + } + break; + } + + case GPBDataTypeBool: { + BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j] + : GPBGetMessageBoolField(message, field)); + [toStr appendString:(v ? @"true" : @"false")]; + break; + } + + case GPBDataTypeString: { + NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] + : GPBGetMessageStringField(message, field)); + AppendStringEscaped(v, toStr); + break; + } + + case GPBDataTypeBytes: { + NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] + : GPBGetMessageBytesField(message, field)); + AppendBufferAsString(v, toStr); + break; + } + + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + GPBMessage *v = + (isRepeated ? [(NSArray *)array objectAtIndex:j] + : GPBGetObjectIvarWithField(message, field)); + [toStr appendFormat:@"{%@\n", lineEnding]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(v, toStr, subIndent); + [toStr appendFormat:@"%@}", lineIndent]; + lineEnding = @""; + break; + } + + } // switch(fieldDataType) + + // End the line. + [toStr appendFormat:@"%@\n", lineEnding]; + + } // for(count) +} + +static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, + NSArray *activeExtensions, + GPBExtensionRange range, + NSMutableString *toStr, + NSString *lineIndent) { + uint32_t start = range.start; + uint32_t end = range.end; + for (GPBExtensionDescriptor *extension in activeExtensions) { + uint32_t fieldNumber = extension.fieldNumber; + if (fieldNumber < start) { + // Not there yet. + continue; + } + if (fieldNumber >= end) { + // Done. + break; + } + + id rawExtValue = [message getExtension:extension]; + BOOL isRepeated = extension.isRepeated; + + NSUInteger numValues = 1; + NSString *lineEnding = @""; + if (isRepeated) { + numValues = [(NSArray *)rawExtValue count]; + } + + NSString *singletonName = extension.singletonName; + if (numValues == 1) { + lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName]; + } else { + [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName]; + } + + GPBDataType extDataType = extension.dataType; + for (NSUInteger j = 0; j < numValues; ++j) { + id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue); + + // Start the line. + [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber, + (GPBDataTypeIsMessage(extDataType) ? "" : ":")]; + + // The value. + switch (extDataType) { +#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ + } + + FIELD_CASE(Int32, int32_t, intValue, @"%d") + FIELD_CASE(SInt32, int32_t, intValue, @"%d") + FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d") + FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u") + FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u") + FIELD_CASE(Int64, int64_t, longLongValue, @"%lld") + FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld") + FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld") + FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu") + FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu") + FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG) + FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG) + // TODO: Add a comment with the enum name from enum descriptors + // (might not be real value, so leave it as a comment, ObjC compiler + // name mangles differently). Doesn't look like we actually generate + // an enum descriptor reference like we do for normal fields, so this + // will take a compiler change. + FIELD_CASE(Enum, int32_t, intValue, @"%d") + +#undef FIELD_CASE + + case GPBDataTypeBool: + [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" + : @"false")]; + break; + + case GPBDataTypeString: + AppendStringEscaped(curValue, toStr); + break; + + case GPBDataTypeBytes: + AppendBufferAsString((NSData *)curValue, toStr); + break; + + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + [toStr appendFormat:@"{%@\n", lineEnding]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + AppendTextFormatForMessage(curValue, toStr, subIndent); + [toStr appendFormat:@"%@}", lineIndent]; + lineEnding = @""; + break; + } + + } // switch(extDataType) + + // End the line. + [toStr appendFormat:@"%@\n", lineEnding]; + + } // for(numValues) + + } // for..in(activeExtensions) +} + +static void AppendTextFormatForMessage(GPBMessage *message, + NSMutableString *toStr, + NSString *lineIndent) { + GPBDescriptor *descriptor = [message descriptor]; + NSArray *fieldsArray = descriptor->fields_; + NSUInteger fieldCount = fieldsArray.count; + const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; + NSUInteger extensionRangesCount = descriptor.extensionRangesCount; + NSArray *activeExtensions = [[message extensionsCurrentlySet] + sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; + for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { + if (i == fieldCount) { + AppendTextFormatForMessageExtensionRange( + message, activeExtensions, extensionRanges[j++], toStr, lineIndent); + } else if (j == extensionRangesCount || + GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { + AppendTextFormatForMessageField(message, fieldsArray[i++], toStr, + lineIndent); + } else { + AppendTextFormatForMessageExtensionRange( + message, activeExtensions, extensionRanges[j++], toStr, lineIndent); + } + } + + NSString *unknownFieldsStr = + GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent); + if ([unknownFieldsStr length] > 0) { + [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent]; + [toStr appendString:unknownFieldsStr]; + } +} + +NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { + if (message == nil) return @""; + if (lineIndent == nil) lineIndent = @""; + + NSMutableString *buildString = [NSMutableString string]; + AppendTextFormatForMessage(message, buildString, lineIndent); + return buildString; +} + +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, + NSString *lineIndent) { + if (unknownSet == nil) return @""; + if (lineIndent == nil) lineIndent = @""; + + NSMutableString *result = [NSMutableString string]; + for (GPBUnknownField *field in [unknownSet sortedFields]) { + int32_t fieldNumber = [field number]; + +#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ + [field.PROPNAME \ + enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \ + _Pragma("unused(idx, stop)"); \ + [result \ + appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \ + }]; + + PRINT_LOOP(varintList, uint64_t, %llu); + PRINT_LOOP(fixed32List, uint32_t, 0x%X); + PRINT_LOOP(fixed64List, uint64_t, 0x%llX); + +#undef PRINT_LOOP + + // NOTE: C++ version of TextFormat tries to parse this as a message + // and print that if it succeeds. + for (NSData *data in field.lengthDelimitedList) { + [result appendFormat:@"%@%d: ", lineIndent, fieldNumber]; + AppendBufferAsString(data, result); + [result appendString:@"\n"]; + } + + for (GPBUnknownFieldSet *subUnknownSet in field.groupList) { + [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber]; + NSString *subIndent = [lineIndent stringByAppendingString:@" "]; + NSString *subUnknwonSetStr = + GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent); + [result appendString:subUnknwonSetStr]; + [result appendFormat:@"%@}\n", lineIndent]; + } + } + return result; +} + +// Helpers to decode a varint. Not using GPBCodedInputStream version because +// that needs a state object, and we don't want to create an input stream out +// of the data. +GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) { + int8_t result = *((int8_t *)(*data)); + ++(*data); + return result; +} + +static int32_t ReadRawVarint32FromData(const uint8_t **data) { + int8_t tmp = ReadRawByteFromData(data); + if (tmp >= 0) { + return tmp; + } + int32_t result = tmp & 0x7f; + if ((tmp = ReadRawByteFromData(data)) >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = ReadRawByteFromData(data)) >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = ReadRawByteFromData(data)) >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = ReadRawByteFromData(data)) << 28; + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) { + if (ReadRawByteFromData(data) >= 0) { + return result; + } + } + [NSException raise:NSParseErrorException + format:@"Unable to read varint32"]; + } + } + } + } + return result; +} + +NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, + NSString *inputStr) { + // decodData form: + // varint32: num entries + // for each entry: + // varint32: key + // bytes*: decode data + // + // decode data one of two forms: + // 1: a \0 followed by the string followed by an \0 + // 2: bytecodes to transform an input into the right thing, ending with \0 + // + // the bytes codes are of the form: + // 0xabbccccc + // 0x0 (all zeros), end. + // a - if set, add an underscore + // bb - 00 ccccc bytes as is + // bb - 10 ccccc upper first, as is on rest, ccccc byte total + // bb - 01 ccccc lower first, as is on rest, ccccc byte total + // bb - 11 ccccc all upper, ccccc byte total + + if (!decodeData || !inputStr) { + return nil; + } + + // Find key + const uint8_t *scan = decodeData; + int32_t numEntries = ReadRawVarint32FromData(&scan); + BOOL foundKey = NO; + while (!foundKey && (numEntries > 0)) { + --numEntries; + int32_t dataKey = ReadRawVarint32FromData(&scan); + if (dataKey == key) { + foundKey = YES; + } else { + // If it is a inlined string, it will start with \0; if it is bytecode it + // will start with a code. So advance one (skipping the inline string + // marker), and then loop until reaching the end marker (\0). + ++scan; + while (*scan != 0) ++scan; + // Now move past the end marker. + ++scan; + } + } + + if (!foundKey) { + return nil; + } + + // Decode + + if (*scan == 0) { + // Inline string. Move over the marker, and NSString can take it as + // UTF8. + ++scan; + NSString *result = [NSString stringWithUTF8String:(const char *)scan]; + return result; + } + + NSMutableString *result = + [NSMutableString stringWithCapacity:[inputStr length]]; + + const uint8_t kAddUnderscore = 0b10000000; + const uint8_t kOpMask = 0b01100000; + // const uint8_t kOpAsIs = 0b00000000; + const uint8_t kOpFirstUpper = 0b01000000; + const uint8_t kOpFirstLower = 0b00100000; + const uint8_t kOpAllUpper = 0b01100000; + const uint8_t kSegmentLenMask = 0b00011111; + + NSInteger i = 0; + for (; *scan != 0; ++scan) { + if (*scan & kAddUnderscore) { + [result appendString:@"_"]; + } + int segmentLen = *scan & kSegmentLenMask; + uint8_t decodeOp = *scan & kOpMask; + + // Do op specific handling of the first character. + if (decodeOp == kOpFirstUpper) { + unichar c = [inputStr characterAtIndex:i]; + [result appendFormat:@"%c", toupper((char)c)]; + ++i; + --segmentLen; + } else if (decodeOp == kOpFirstLower) { + unichar c = [inputStr characterAtIndex:i]; + [result appendFormat:@"%c", tolower((char)c)]; + ++i; + --segmentLen; + } + // else op == kOpAsIs || op == kOpAllUpper + + // Now pull over the rest of the length for this segment. + for (int x = 0; x < segmentLen; ++x) { + unichar c = [inputStr characterAtIndex:(i + x)]; + if (decodeOp == kOpAllUpper) { + [result appendFormat:@"%c", toupper((char)c)]; + } else { + [result appendFormat:@"%C", c]; + } + } + i += segmentLen; + } + + return result; +} + +#pragma clang diagnostic pop + +BOOL GPBClassHasSel(Class aClass, SEL sel) { + // NOTE: We have to use class_copyMethodList, all other runtime method + // lookups actually also resolve the method implementation and this + // is called from within those methods. + + BOOL result = NO; + unsigned int methodCount = 0; + Method *methodList = class_copyMethodList(aClass, &methodCount); + for (unsigned int i = 0; i < methodCount; ++i) { + SEL methodSelector = method_getName(methodList[i]); + if (methodSelector == sel) { + result = YES; + break; + } + } + free(methodList); + return result; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities_PackagePrivate.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities_PackagePrivate.h new file mode 100644 index 0000000..ed424ce --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBUtilities_PackagePrivate.h @@ -0,0 +1,351 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +#import "GPBUtilities.h" + +#import "GPBDescriptor_PackagePrivate.h" + +// Macros for stringifying library symbols. These are used in the generated +// PB descriptor classes wherever a library symbol name is represented as a +// string. See README.google for more information. +#define GPBStringify(S) #S +#define GPBStringifySymbol(S) GPBStringify(S) + +#define GPBNSStringify(S) @#S +#define GPBNSStringifySymbol(S) GPBNSStringify(S) + +// Constant to internally mark when there is no has bit. +#define GPBNoHasBit INT32_MAX + +CF_EXTERN_C_BEGIN + +// These two are used to inject a runtime check for version mismatch into the +// generated sources to make sure they are linked with a supporting runtime. +void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion); +GPB_INLINE void GPB_DEBUG_CHECK_RUNTIME_VERSIONS() { + // NOTE: By being inline here, this captures the value from the library's + // headers at the time the generated code was compiled. +#if defined(DEBUG) && DEBUG + GPBCheckRuntimeVersionSupport(GOOGLE_PROTOBUF_OBJC_VERSION); +#endif +} + +// Legacy version of the checks, remove when GOOGLE_PROTOBUF_OBJC_GEN_VERSION +// goes away (see more info in GPBBootstrap.h). +void GPBCheckRuntimeVersionInternal(int32_t version); +GPB_INLINE void GPBDebugCheckRuntimeVersion() { +#if defined(DEBUG) && DEBUG + GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION); +#endif +} + +// Conversion functions for de/serializing floating point types. + +GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) { + union { double f; int64_t i; } u; + u.f = v; + return u.i; +} + +GPB_INLINE int32_t GPBConvertFloatToInt32(float v) { + union { float f; int32_t i; } u; + u.f = v; + return u.i; +} + +GPB_INLINE double GPBConvertInt64ToDouble(int64_t v) { + union { double f; int64_t i; } u; + u.i = v; + return u.f; +} + +GPB_INLINE float GPBConvertInt32ToFloat(int32_t v) { + union { float f; int32_t i; } u; + u.i = v; + return u.f; +} + +GPB_INLINE int32_t GPBLogicalRightShift32(int32_t value, int32_t spaces) { + return (int32_t)((uint32_t)(value) >> spaces); +} + +GPB_INLINE int64_t GPBLogicalRightShift64(int64_t value, int32_t spaces) { + return (int64_t)((uint64_t)(value) >> spaces); +} + +// Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) { + return (int32_t)(GPBLogicalRightShift32((int32_t)n, 1) ^ -((int32_t)(n) & 1)); +} + +// Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) { + return (int64_t)(GPBLogicalRightShift64((int64_t)n, 1) ^ -((int64_t)(n) & 1)); +} + +// Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) { + // Note: the right-shift must be arithmetic + return ((uint32_t)n << 1) ^ (uint32_t)(n >> 31); +} + +// Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers +// into values that can be efficiently encoded with varint. (Otherwise, +// negative values must be sign-extended to 64 bits to be varint encoded, +// thus always taking 10 bytes on the wire.) +GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) { + // Note: the right-shift must be arithmetic + return ((uint64_t)n << 1) ^ (uint64_t)(n >> 63); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +GPB_INLINE BOOL GPBDataTypeIsObject(GPBDataType type) { + switch (type) { + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return YES; + default: + return NO; + } +} + +GPB_INLINE BOOL GPBDataTypeIsMessage(GPBDataType type) { + switch (type) { + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return YES; + default: + return NO; + } +} + +GPB_INLINE BOOL GPBFieldDataTypeIsMessage(GPBFieldDescriptor *field) { + return GPBDataTypeIsMessage(field->description_->dataType); +} + +GPB_INLINE BOOL GPBFieldDataTypeIsObject(GPBFieldDescriptor *field) { + return GPBDataTypeIsObject(field->description_->dataType); +} + +GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) { + return GPBDataTypeIsMessage(ext->description_->dataType); +} + +// The field is an array/map or it has an object value. +GPB_INLINE BOOL GPBFieldStoresObject(GPBFieldDescriptor *field) { + GPBMessageFieldDescription *desc = field->description_; + if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) { + return YES; + } + return GPBDataTypeIsObject(desc->dataType); +} + +BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber); +void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, + BOOL value); +uint32_t GPBGetHasOneof(GPBMessage *self, int32_t index); + +GPB_INLINE BOOL +GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) { + GPBMessageFieldDescription *fieldDesc = field->description_; + return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number); +} +GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field, + BOOL value) { + GPBMessageFieldDescription *fieldDesc = field->description_; + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value); +} + +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); + +#pragma clang diagnostic pop + +//%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE) +//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value, +//% NAME$S GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL) +// This block of code is generated, do not edit it directly. + +void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t) +// This block of code is generated, do not edit it directly. + +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t) +// This block of code is generated, do not edit it directly. + +void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t) +// This block of code is generated, do not edit it directly. + +void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t) +// This block of code is generated, do not edit it directly. + +void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float) +// This block of code is generated, do not edit it directly. + +void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + float value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double) +// This block of code is generated, do not edit it directly. + +void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + double value, + GPBFileSyntax syntax); +//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t) +// This block of code is generated, do not edit it directly. + +void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax); +//%PDDM-EXPAND-END (8 expansions) + +int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + GPBFileSyntax syntax); + +id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); + +void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, id value, + GPBFileSyntax syntax); +void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) + value, + GPBFileSyntax syntax); + +// GPBGetObjectIvarWithField will automatically create the field (message) if +// it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil. +id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, + GPBFieldDescriptor *field); + +void GPBSetAutocreatedRetainedObjectIvarWithField( + GPBMessage *self, GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) value); + +// Clears and releases the autocreated message ivar, if it's autocreated. If +// it's not set as autocreated, this method does nothing. +void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field); + +// Returns an Objective C encoding for |selector|. |instanceSel| should be +// YES if it's an instance selector (as opposed to a class selector). +// |selector| must be a selector from MessageSignatureProtocol. +const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel); + +// Helper for text format name encoding. +// decodeData is the data describing the sepecial decodes. +// key and inputString are the input that needs decoding. +NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, + NSString *inputString); + +// A series of selectors that are used solely to get @encoding values +// for them by the dynamic protobuf runtime code. See +// GPBMessageEncodingForSelector for details. GPBRootObject conforms to +// the protocol so that it is encoded in the Objective C runtime. +@protocol GPBMessageSignatureProtocol +@optional + +#define GPB_MESSAGE_SIGNATURE_ENTRY(TYPE, NAME) \ + -(TYPE)get##NAME; \ + -(void)set##NAME : (TYPE)value; \ + -(TYPE)get##NAME##AtIndex : (NSUInteger)index; + +GPB_MESSAGE_SIGNATURE_ENTRY(BOOL, Bool) +GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, Fixed32) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SFixed32) +GPB_MESSAGE_SIGNATURE_ENTRY(float, Float) +GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, Fixed64) +GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SFixed64) +GPB_MESSAGE_SIGNATURE_ENTRY(double, Double) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Int32) +GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, Int64) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SInt32) +GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SInt64) +GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, UInt32) +GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, UInt64) +GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Bytes) +GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String) +GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message) +GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group) +GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Enum) + +#undef GPB_MESSAGE_SIGNATURE_ENTRY + +- (id)getArray; +- (NSUInteger)getArrayCount; +- (void)setArray:(NSArray *)array; ++ (id)getClassValue; +@end + +BOOL GPBClassHasSel(Class aClass, SEL sel); + +CF_EXTERN_C_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.h new file mode 100644 index 0000000..04df417 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.h @@ -0,0 +1,245 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "google/protobuf/Any.pbobjc.h" + #import "google/protobuf/Duration.pbobjc.h" + #import "google/protobuf/Timestamp.pbobjc.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Errors + +/** NSError domain used for errors. */ +extern NSString *const GPBWellKnownTypesErrorDomain; + +/** Error code for NSError with GPBWellKnownTypesErrorDomain. */ +typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) { + /** The type_url could not be computed for the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeFailedToComputeTypeURL = -100, + /** type_url in a Any doesn’t match that of the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeTypeURLMismatch = -101, +}; + +#pragma mark - GPBTimestamp + +/** + * Category for GPBTimestamp to work with standard Foundation time/date types. + **/ +@interface GPBTimestamp (GBPWellKnownTypes) + +/** The NSDate representation of this GPBTimestamp. */ +@property(nonatomic, readwrite, strong) NSDate *date; + +/** + * The NSTimeInterval representation of this GPBTimestamp. + * + * @note: Not all second/nanos combinations can be represented in a + * NSTimeInterval, so getting this could be a lossy transform. + **/ +@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970; + +/** + * Initializes a GPBTimestamp with the given NSDate. + * + * @param date The date to configure the GPBTimestamp with. + * + * @return A newly initialized GPBTimestamp. + **/ +- (instancetype)initWithDate:(NSDate *)date; + +/** + * Initializes a GPBTimestamp with the given NSTimeInterval. + * + * @param timeIntervalSince1970 Time interval to configure the GPBTimestamp with. + * + * @return A newly initialized GPBTimestamp. + **/ +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970; + +@end + +#pragma mark - GPBDuration + +/** + * Category for GPBDuration to work with standard Foundation time type. + **/ +@interface GPBDuration (GBPWellKnownTypes) + +/** + * The NSTimeInterval representation of this GPBDuration. + * + * @note: Not all second/nanos combinations can be represented in a + * NSTimeInterval, so getting this could be a lossy transform. + **/ +@property(nonatomic, readwrite) NSTimeInterval timeInterval; + +/** + * Initializes a GPBDuration with the given NSTimeInterval. + * + * @param timeInterval Time interval to configure the GPBDuration with. + * + * @return A newly initialized GPBDuration. + **/ +- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval; + +// These next two methods are deprecated because GBPDuration has no need of a +// "base" time. The older methods were about symmetry with GBPTimestamp, but +// the unix epoch usage is too confusing. + +/** Deprecated, use timeInterval instead. */ +@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970 + __attribute__((deprecated("Use timeInterval"))); +/** Deprecated, use initWithTimeInterval: instead. */ +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 + __attribute__((deprecated("Use initWithTimeInterval:"))); + +@end + +#pragma mark - GPBAny + +/** + * Category for GPBAny to help work with the message within the object. + **/ +@interface GPBAny (GBPWellKnownTypes) + +/** + * Convenience method to create a GPBAny containing the serialized message. + * This uses type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Convenience method to create a GPBAny containing the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Unpacks the serialized message as if it was an instance of the given class. + * + * @note When checking type_url, the base URL is not checked, only the fully + * qualified name. + * + * @param messageClass The class to use to deserialize the contained message. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return An instance of the given class populated with the contained data, or + * nil on failure. + */ +- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr; + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.m new file mode 100644 index 0000000..2808afe --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWellKnownTypes.m @@ -0,0 +1,272 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Importing sources here to force the linker to include our category methods in +// the static library. If these were compiled separately, the category methods +// below would be stripped by the linker. + +#import "GPBWellKnownTypes.h" + +#import "GPBUtilities_PackagePrivate.h" + +NSString *const GPBWellKnownTypesErrorDomain = + GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain); + +static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/"; + +static NSTimeInterval TimeIntervalFromSecondsAndNanos(int64_t seconds, + int32_t nanos) { + return seconds + (NSTimeInterval)nanos / 1e9; +} + +static int32_t SecondsAndNanosFromTimeInterval(NSTimeInterval time, + int64_t *outSeconds, + BOOL nanosMustBePositive) { + NSTimeInterval seconds; + NSTimeInterval nanos = modf(time, &seconds); + + if (nanosMustBePositive && (nanos < 0)) { + // Per Timestamp.proto, nanos is non-negative and "Negative second values with + // fractions must still have non-negative nanos values that count forward in + // time. Must be from 0 to 999,999,999 inclusive." + --seconds; + nanos = 1.0 + nanos; + } + + nanos *= 1e9; + *outSeconds = (int64_t)seconds; + return (int32_t)nanos; +} + +static NSString *BuildTypeURL(NSString *typeURLPrefix, NSString *fullName) { + if (typeURLPrefix.length == 0) { + return fullName; + } + + if ([typeURLPrefix hasSuffix:@"/"]) { + return [typeURLPrefix stringByAppendingString:fullName]; + } + + return [NSString stringWithFormat:@"%@/%@", typeURLPrefix, fullName]; +} + +static NSString *ParseTypeFromURL(NSString *typeURLString) { + NSRange range = [typeURLString rangeOfString:@"/" options:NSBackwardsSearch]; + if ((range.location == NSNotFound) || + (NSMaxRange(range) == typeURLString.length)) { + return nil; + } + NSString *result = [typeURLString substringFromIndex:range.location + 1]; + return result; +} + +#pragma mark - GPBTimestamp + +@implementation GPBTimestamp (GBPWellKnownTypes) + +- (instancetype)initWithDate:(NSDate *)date { + return [self initWithTimeIntervalSince1970:date.timeIntervalSince1970]; +} + +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + if ((self = [super init])) { + int64_t seconds; + int32_t nanos = SecondsAndNanosFromTimeInterval( + timeIntervalSince1970, &seconds, YES); + self.seconds = seconds; + self.nanos = nanos; + } + return self; +} + +- (NSDate *)date { + return [NSDate dateWithTimeIntervalSince1970:self.timeIntervalSince1970]; +} + +- (void)setDate:(NSDate *)date { + self.timeIntervalSince1970 = date.timeIntervalSince1970; +} + +- (NSTimeInterval)timeIntervalSince1970 { + return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); +} + +- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + int64_t seconds; + int32_t nanos = + SecondsAndNanosFromTimeInterval(timeIntervalSince1970, &seconds, YES); + self.seconds = seconds; + self.nanos = nanos; +} + +@end + +#pragma mark - GPBDuration + +@implementation GPBDuration (GBPWellKnownTypes) + +- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval { + if ((self = [super init])) { + int64_t seconds; + int32_t nanos = SecondsAndNanosFromTimeInterval( + timeInterval, &seconds, NO); + self.seconds = seconds; + self.nanos = nanos; + } + return self; +} + +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + return [self initWithTimeInterval:timeIntervalSince1970]; +} + +- (NSTimeInterval)timeInterval { + return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); +} + +- (void)setTimeInterval:(NSTimeInterval)timeInterval { + int64_t seconds; + int32_t nanos = + SecondsAndNanosFromTimeInterval(timeInterval, &seconds, NO); + self.seconds = seconds; + self.nanos = nanos; +} + +- (NSTimeInterval)timeIntervalSince1970 { + return self.timeInterval; +} + +- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + self.timeInterval = timeIntervalSince1970; +} + +@end + +#pragma mark - GPBAny + +@implementation GPBAny (GBPWellKnownTypes) + ++ (instancetype)anyWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self anyWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + ++ (instancetype)anyWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + return [[[self alloc] initWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr] autorelease]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self initWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + self = [self init]; + if (self) { + if (![self packWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr]) { + [self release]; + self = nil; + } + } + return self; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self packWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + NSString *fullName = [message descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return NO; + } + if (errorPtr) { + *errorPtr = nil; + } + self.typeURL = BuildTypeURL(typeURLPrefix, fullName); + self.value = message.data; + return YES; +} + +- (GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr { + NSString *fullName = [messageClass descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return nil; + } + + NSString *expectedFullName = ParseTypeFromURL(self.typeURL); + if ((expectedFullName == nil) || ![expectedFullName isEqual:fullName]) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeTypeURLMismatch + userInfo:nil]; + } + return nil; + } + + // Any is proto3, which means no extensions, so this assumes anything put + // within an any also won't need extensions. A second helper could be added + // if needed. + return [messageClass parseFromData:self.value + error:errorPtr]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWireFormat.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWireFormat.h new file mode 100644 index 0000000..c5941a3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWireFormat.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBRuntimeTypes.h" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +typedef enum { + GPBWireFormatVarint = 0, + GPBWireFormatFixed64 = 1, + GPBWireFormatLengthDelimited = 2, + GPBWireFormatStartGroup = 3, + GPBWireFormatEndGroup = 4, + GPBWireFormatFixed32 = 5, +} GPBWireFormat; + +enum { + GPBWireFormatMessageSetItem = 1, + GPBWireFormatMessageSetTypeId = 2, + GPBWireFormatMessageSetMessage = 3 +}; + +uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) + __attribute__((const)); +GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const)); +uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const)); +BOOL GPBWireFormatIsValidTag(uint32_t tag) __attribute__((const)); + +GPBWireFormat GPBWireFormatForType(GPBDataType dataType, BOOL isPacked) + __attribute__((const)); + +#define GPBWireFormatMessageSetItemTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatStartGroup)) +#define GPBWireFormatMessageSetItemEndTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatEndGroup)) +#define GPBWireFormatMessageSetTypeIdTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetTypeId, GPBWireFormatVarint)) +#define GPBWireFormatMessageSetMessageTag \ + (GPBWireFormatMakeTag(GPBWireFormatMessageSetMessage, \ + GPBWireFormatLengthDelimited)) + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWireFormat.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWireFormat.m new file mode 100644 index 0000000..860a339 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/GPBWireFormat.m @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBWireFormat.h" + +#import "GPBUtilities_PackagePrivate.h" + +enum { + GPBWireFormatTagTypeBits = 3, + GPBWireFormatTagTypeMask = 7 /* = (1 << GPBWireFormatTagTypeBits) - 1 */, +}; + +uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) { + return (fieldNumber << GPBWireFormatTagTypeBits) | wireType; +} + +GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) { + return (GPBWireFormat)(tag & GPBWireFormatTagTypeMask); +} + +uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) { + return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits); +} + +BOOL GPBWireFormatIsValidTag(uint32_t tag) { + uint32_t formatBits = (tag & GPBWireFormatTagTypeMask); + // The valid GPBWireFormat* values are 0-5, anything else is not a valid tag. + BOOL result = (formatBits <= 5); + return result; +} + +GPBWireFormat GPBWireFormatForType(GPBDataType type, BOOL isPacked) { + if (isPacked) { + return GPBWireFormatLengthDelimited; + } + + static const GPBWireFormat format[GPBDataType_Count] = { + GPBWireFormatVarint, // GPBDataTypeBool + GPBWireFormatFixed32, // GPBDataTypeFixed32 + GPBWireFormatFixed32, // GPBDataTypeSFixed32 + GPBWireFormatFixed32, // GPBDataTypeFloat + GPBWireFormatFixed64, // GPBDataTypeFixed64 + GPBWireFormatFixed64, // GPBDataTypeSFixed64 + GPBWireFormatFixed64, // GPBDataTypeDouble + GPBWireFormatVarint, // GPBDataTypeInt32 + GPBWireFormatVarint, // GPBDataTypeInt64 + GPBWireFormatVarint, // GPBDataTypeSInt32 + GPBWireFormatVarint, // GPBDataTypeSInt64 + GPBWireFormatVarint, // GPBDataTypeUInt32 + GPBWireFormatVarint, // GPBDataTypeUInt64 + GPBWireFormatLengthDelimited, // GPBDataTypeBytes + GPBWireFormatLengthDelimited, // GPBDataTypeString + GPBWireFormatLengthDelimited, // GPBDataTypeMessage + GPBWireFormatStartGroup, // GPBDataTypeGroup + GPBWireFormatVarint // GPBDataTypeEnum + }; + return format[type]; +} diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.h new file mode 100644 index 0000000..2091d72 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.h @@ -0,0 +1,183 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBAnyRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBAnyRoot : GPBRootObject +@end + +#pragma mark - GPBAny + +typedef GPB_ENUM(GPBAny_FieldNumber) { + GPBAny_FieldNumber_TypeURL = 1, + GPBAny_FieldNumber_Value = 2, +}; + +/** + * `Any` contains an arbitrary serialized protocol buffer message along with a + * URL that describes the type of the serialized message. + * + * Protobuf library provides support to pack/unpack Any values in the form + * of utility functions or additional generated methods of the Any type. + * + * Example 1: Pack and unpack a message in C++. + * + * Foo foo = ...; + * Any any; + * any.PackFrom(foo); + * ... + * if (any.UnpackTo(&foo)) { + * ... + * } + * + * Example 2: Pack and unpack a message in Java. + * + * Foo foo = ...; + * Any any = Any.pack(foo); + * ... + * if (any.is(Foo.class)) { + * foo = any.unpack(Foo.class); + * } + * + * Example 3: Pack and unpack a message in Python. + * + * foo = Foo(...) + * any = Any() + * any.Pack(foo) + * ... + * if any.Is(Foo.DESCRIPTOR): + * any.Unpack(foo) + * ... + * + * Example 4: Pack and unpack a message in Go + * + * foo := &pb.Foo{...} + * any, err := ptypes.MarshalAny(foo) + * ... + * foo := &pb.Foo{} + * if err := ptypes.UnmarshalAny(any, foo); err != nil { + * ... + * } + * + * The pack methods provided by protobuf library will by default use + * 'type.googleapis.com/full.type.name' as the type URL and the unpack + * methods only use the fully qualified type name after the last '/' + * in the type URL, for example "foo.bar.com/x/y.z" will yield type + * name "y.z". + * + * + * JSON + * ==== + * The JSON representation of an `Any` value uses the regular + * representation of the deserialized, embedded message, with an + * additional field `\@type` which contains the type URL. Example: + * + * package google.profile; + * message Person { + * string first_name = 1; + * string last_name = 2; + * } + * + * { + * "\@type": "type.googleapis.com/google.profile.Person", + * "firstName": , + * "lastName": + * } + * + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `\@type` + * field. Example (for message [google.protobuf.Duration][]): + * + * { + * "\@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + **/ +@interface GPBAny : GPBMessage + +/** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; + +/** Must be a valid serialized protocol buffer of the above specified type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.m new file mode 100644 index 0000000..7ca84ff --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Any.pbobjc.m @@ -0,0 +1,114 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Any.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBAnyRoot + +@implementation GPBAnyRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBAnyRoot_FileDescriptor + +static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBAny + +@implementation GPBAny + +@dynamic typeURL; +@dynamic value; + +typedef struct GPBAny__storage_ { + uint32_t _has_storage_[1]; + NSString *typeURL; + NSData *value; +} GPBAny__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "typeURL", + .dataTypeSpecific.className = NULL, + .number = GPBAny_FieldNumber_TypeURL, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBAny_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBAny__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBAny class] + rootClass:[GPBAnyRoot class] + file:GPBAnyRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBAny__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\004\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.h new file mode 100644 index 0000000..c93f3f1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.h @@ -0,0 +1,311 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBMethod; +@class GPBMixin; +@class GPBOption; +@class GPBSourceContext; +GPB_ENUM_FWD_DECLARE(GPBSyntax); + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBApiRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBApiRoot : GPBRootObject +@end + +#pragma mark - GPBApi + +typedef GPB_ENUM(GPBApi_FieldNumber) { + GPBApi_FieldNumber_Name = 1, + GPBApi_FieldNumber_MethodsArray = 2, + GPBApi_FieldNumber_OptionsArray = 3, + GPBApi_FieldNumber_Version = 4, + GPBApi_FieldNumber_SourceContext = 5, + GPBApi_FieldNumber_MixinsArray = 6, + GPBApi_FieldNumber_Syntax = 7, +}; + +/** + * Api is a light-weight descriptor for an API Interface. + * + * Interfaces are also described as "protocol buffer services" in some contexts, + * such as by the "service" keyword in a .proto file, but they are different + * from API Services, which represent a concrete implementation of an interface + * as opposed to simply a description of methods and bindings. They are also + * sometimes simply referred to as "APIs" in other contexts, such as the name of + * this message itself. See https://cloud.google.com/apis/design/glossary for + * detailed terminology. + **/ +@interface GPBApi : GPBMessage + +/** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** The methods of this interface, in unspecified order. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodsArray; +/** The number of items in @c methodsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger methodsArray_Count; + +/** Any metadata attached to the interface. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *version; + +/** + * Source context for the protocol buffer service represented by this + * message. + **/ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** Included interfaces. See [Mixin][]. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *mixinsArray; +/** The number of items in @c mixinsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger mixinsArray_Count; + +/** The source syntax of the service. */ +@property(nonatomic, readwrite) enum GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBApi's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBApi_Syntax_RawValue(GPBApi *message); +/** + * Sets the raw value of an @c GPBApi's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value); + +#pragma mark - GPBMethod + +typedef GPB_ENUM(GPBMethod_FieldNumber) { + GPBMethod_FieldNumber_Name = 1, + GPBMethod_FieldNumber_RequestTypeURL = 2, + GPBMethod_FieldNumber_RequestStreaming = 3, + GPBMethod_FieldNumber_ResponseTypeURL = 4, + GPBMethod_FieldNumber_ResponseStreaming = 5, + GPBMethod_FieldNumber_OptionsArray = 6, + GPBMethod_FieldNumber_Syntax = 7, +}; + +/** + * Method represents a method of an API interface. + **/ +@interface GPBMethod : GPBMessage + +/** The simple name of this method. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** A URL of the input message type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL; + +/** If true, the request is streamed. */ +@property(nonatomic, readwrite) BOOL requestStreaming; + +/** The URL of the output message type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL; + +/** If true, the response is streamed. */ +@property(nonatomic, readwrite) BOOL responseStreaming; + +/** Any metadata attached to the method. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source syntax of this method. */ +@property(nonatomic, readwrite) enum GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBMethod's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBMethod_Syntax_RawValue(GPBMethod *message); +/** + * Sets the raw value of an @c GPBMethod's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value); + +#pragma mark - GPBMixin + +typedef GPB_ENUM(GPBMixin_FieldNumber) { + GPBMixin_FieldNumber_Name = 1, + GPBMixin_FieldNumber_Root = 2, +}; + +/** + * Declares an API Interface to be included in this interface. The including + * interface must redeclare all the methods from the included interface, but + * documentation and options are inherited as follows: + * + * - If after comment and whitespace stripping, the documentation + * string of the redeclared method is empty, it will be inherited + * from the original method. + * + * - Each annotation belonging to the service config (http, + * visibility) which is not set in the redeclared method will be + * inherited. + * + * - If an http annotation is inherited, the path pattern will be + * modified as follows. Any version prefix will be replaced by the + * version of the including interface plus the [root][] path if + * specified. + * + * Example of a simple mixin: + * + * package google.acl.v1; + * service AccessControl { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v1/{resource=**}:getAcl"; + * } + * } + * + * package google.storage.v2; + * service Storage { + * rpc GetAcl(GetAclRequest) returns (Acl); + * + * // Get a data record. + * rpc GetData(GetDataRequest) returns (Data) { + * option (google.api.http).get = "/v2/{resource=**}"; + * } + * } + * + * Example of a mixin configuration: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * + * The mixin construct implies that all methods in `AccessControl` are + * also declared with same name and request/response types in + * `Storage`. A documentation generator or annotation processor will + * see the effective `Storage.GetAcl` method after inherting + * documentation and annotations as follows: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/{resource=**}:getAcl"; + * } + * ... + * } + * + * Note how the version in the path pattern changed from `v1` to `v2`. + * + * If the `root` field in the mixin is specified, it should be a + * relative path under which inherited HTTP paths are placed. Example: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * root: acls + * + * This implies the following inherited HTTP annotation: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + * } + * ... + * } + **/ +@interface GPBMixin : GPBMessage + +/** The fully qualified name of the interface which is included. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *root; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.m new file mode 100644 index 0000000..d63a3e6 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Api.pbobjc.m @@ -0,0 +1,362 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "google/protobuf/Api.pbobjc.h" + #import "google/protobuf/SourceContext.pbobjc.h" + #import "google/protobuf/Type.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBApiRoot + +@implementation GPBApiRoot + +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. + +@end + +#pragma mark - GPBApiRoot_FileDescriptor + +static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBApi + +@implementation GPBApi + +@dynamic name; +@dynamic methodsArray, methodsArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic version; +@dynamic hasSourceContext, sourceContext; +@dynamic mixinsArray, mixinsArray_Count; +@dynamic syntax; + +typedef struct GPBApi__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *methodsArray; + NSMutableArray *optionsArray; + NSString *version; + GPBSourceContext *sourceContext; + NSMutableArray *mixinsArray; +} GPBApi__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBApi_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBApi__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "methodsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod), + .number = GPBApi_FieldNumber_MethodsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBApi_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "version", + .dataTypeSpecific.className = NULL, + .number = GPBApi_FieldNumber_Version, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBApi__storage_, version), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "sourceContext", + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .number = GPBApi_FieldNumber_SourceContext, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "mixinsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBMixin), + .number = GPBApi_FieldNumber_MixinsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBApi_FieldNumber_Syntax, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBApi__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBApi class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBApi__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBApi_Syntax_RawValue(GPBApi *message) { + GPBDescriptor *descriptor = [GPBApi descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) { + GPBDescriptor *descriptor = [GPBApi descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBMethod + +@implementation GPBMethod + +@dynamic name; +@dynamic requestTypeURL; +@dynamic requestStreaming; +@dynamic responseTypeURL; +@dynamic responseStreaming; +@dynamic optionsArray, optionsArray_Count; +@dynamic syntax; + +typedef struct GPBMethod__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSString *requestTypeURL; + NSString *responseTypeURL; + NSMutableArray *optionsArray; +} GPBMethod__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBMethod__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "requestTypeURL", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_RequestTypeURL, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "requestStreaming", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_RequestStreaming, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "responseTypeURL", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_ResponseTypeURL, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "responseStreaming", + .dataTypeSpecific.className = NULL, + .number = GPBMethod_FieldNumber_ResponseStreaming, + .hasIndex = 5, + .offset = 6, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBMethod_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBMethod_FieldNumber_Syntax, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethod class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBMethod__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\002\002\007\244\241!!\000\004\010\244\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) { + GPBDescriptor *descriptor = [GPBMethod descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) { + GPBDescriptor *descriptor = [GPBMethod descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBMixin + +@implementation GPBMixin + +@dynamic name; +@dynamic root; + +typedef struct GPBMixin__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + NSString *root; +} GPBMixin__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBMixin_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBMixin__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "root", + .dataTypeSpecific.className = NULL, + .number = GPBMixin_FieldNumber_Root, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBMixin__storage_, root), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMixin class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBMixin__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.h new file mode 100644 index 0000000..3e36759 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.h @@ -0,0 +1,145 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBDurationRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBDurationRoot : GPBRootObject +@end + +#pragma mark - GPBDuration + +typedef GPB_ENUM(GPBDuration_FieldNumber) { + GPBDuration_FieldNumber_Seconds = 1, + GPBDuration_FieldNumber_Nanos = 2, +}; + +/** + * A Duration represents a signed, fixed-length span of time represented + * as a count of seconds and fractions of seconds at nanosecond + * resolution. It is independent of any calendar and concepts like "day" + * or "month". It is related to Timestamp in that the difference between + * two Timestamp values is a Duration and it can be added or subtracted + * from a Timestamp. Range is approximately +-10,000 years. + * + * # Examples + * + * Example 1: Compute Duration from two Timestamps in pseudo code. + * + * Timestamp start = ...; + * Timestamp end = ...; + * Duration duration = ...; + * + * duration.seconds = end.seconds - start.seconds; + * duration.nanos = end.nanos - start.nanos; + * + * if (duration.seconds < 0 && duration.nanos > 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (durations.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * + * Example 3: Compute Duration from datetime.timedelta in Python. + * + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * + * # JSON Mapping + * + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + **/ +@interface GPBDuration : GPBMessage + +/** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + **/ +@property(nonatomic, readwrite) int64_t seconds; + +/** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + **/ +@property(nonatomic, readwrite) int32_t nanos; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.m new file mode 100644 index 0000000..3fa7024 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Duration.pbobjc.m @@ -0,0 +1,109 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Duration.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBDurationRoot + +@implementation GPBDurationRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBDurationRoot_FileDescriptor + +static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDuration + +@implementation GPBDuration + +@dynamic seconds; +@dynamic nanos; + +typedef struct GPBDuration__storage_ { + uint32_t _has_storage_[1]; + int32_t nanos; + int64_t seconds; +} GPBDuration__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "seconds", + .dataTypeSpecific.className = NULL, + .number = GPBDuration_FieldNumber_Seconds, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "nanos", + .dataTypeSpecific.className = NULL, + .number = GPBDuration_FieldNumber_Nanos, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDuration class] + rootClass:[GPBDurationRoot class] + file:GPBDurationRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBDuration__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.h new file mode 100644 index 0000000..fdc247a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.h @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBEmptyRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBEmptyRoot : GPBRootObject +@end + +#pragma mark - GPBEmpty + +/** + * A generic empty message that you can re-use to avoid defining duplicated + * empty messages in your APIs. A typical example is to use it as the request + * or the response type of an API method. For instance: + * + * service Foo { + * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + * } + * + * The JSON representation for `Empty` is empty JSON object `{}`. + **/ +@interface GPBEmpty : GPBMessage + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.m new file mode 100644 index 0000000..51f15f3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Empty.pbobjc.m @@ -0,0 +1,85 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Empty.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBEmptyRoot + +@implementation GPBEmptyRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBEmptyRoot_FileDescriptor + +static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBEmpty + +@implementation GPBEmpty + + +typedef struct GPBEmpty__storage_ { + uint32_t _has_storage_[1]; +} GPBEmpty__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] + rootClass:[GPBEmptyRoot class] + file:GPBEmptyRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GPBEmpty__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.h new file mode 100644 index 0000000..72cac9a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -0,0 +1,273 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBFieldMaskRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBFieldMaskRoot : GPBRootObject +@end + +#pragma mark - GPBFieldMask + +typedef GPB_ENUM(GPBFieldMask_FieldNumber) { + GPBFieldMask_FieldNumber_PathsArray = 1, +}; + +/** + * `FieldMask` represents a set of symbolic field paths, for example: + * + * paths: "f.a" + * paths: "f.b.d" + * + * Here `f` represents a field in some root message, `a` and `b` + * fields in the message found in `f`, and `d` a field found in the + * message in `f.b`. + * + * Field masks are used to specify a subset of fields that should be + * returned by a get operation or modified by an update operation. + * Field masks also have a custom JSON encoding (see below). + * + * # Field Masks in Projections + * + * When used in the context of a projection, a response message or + * sub-message is filtered by the API to only contain those fields as + * specified in the mask. For example, if the mask in the previous + * example is applied to a response message as follows: + * + * f { + * a : 22 + * b { + * d : 1 + * x : 2 + * } + * y : 13 + * } + * z: 8 + * + * The result will not contain specific values for fields x,y and z + * (their value will be set to the default, and omitted in proto text + * output): + * + * + * f { + * a : 22 + * b { + * d : 1 + * } + * } + * + * A repeated field is not allowed except at the last position of a + * paths string. + * + * If a FieldMask object is not present in a get operation, the + * operation applies to all fields (as if a FieldMask of all fields + * had been specified). + * + * Note that a field mask does not necessarily apply to the + * top-level response message. In case of a REST get operation, the + * field mask applies directly to the response, but in case of a REST + * list operation, the mask instead applies to each individual message + * in the returned resource list. In case of a REST custom method, + * other definitions may be used. Where the mask applies will be + * clearly documented together with its declaration in the API. In + * any case, the effect on the returned resource/resources is required + * behavior for APIs. + * + * # Field Masks in Update Operations + * + * A field mask in update operations specifies which fields of the + * targeted resource are going to be updated. The API is required + * to only change the values of the fields as specified in the mask + * and leave the others untouched. If a resource is passed in to + * describe the updated values, the API ignores the values of all + * fields not covered by the mask. + * + * If a repeated field is specified for an update operation, new values will + * be appended to the existing repeated field in the target resource. Note that + * a repeated field is only allowed in the last position of a `paths` string. + * + * If a sub-message is specified in the last position of the field mask for an + * update operation, then new value will be merged into the existing sub-message + * in the target resource. + * + * For example, given the target message: + * + * f { + * b { + * d: 1 + * x: 2 + * } + * c: [1] + * } + * + * And an update message: + * + * f { + * b { + * d: 10 + * } + * c: [2] + * } + * + * then if the field mask is: + * + * paths: ["f.b", "f.c"] + * + * then the result will be: + * + * f { + * b { + * d: 10 + * x: 2 + * } + * c: [1, 2] + * } + * + * An implementation may provide options to override this default behavior for + * repeated and message fields. + * + * In order to reset a field's value to the default, the field must + * be in the mask and set to the default value in the provided resource. + * Hence, in order to reset all fields of a resource, provide a default + * instance of the resource and set all fields in the mask, or do + * not provide a mask as described below. + * + * If a field mask is not present on update, the operation applies to + * all fields (as if a field mask of all fields has been specified). + * Note that in the presence of schema evolution, this may mean that + * fields the client does not know and has therefore not filled into + * the request will be reset to their default. If this is unwanted + * behavior, a specific service may require a client to always specify + * a field mask, producing an error if not. + * + * As with get operations, the location of the resource which + * describes the updated values in the request message depends on the + * operation kind. In any case, the effect of the field mask is + * required to be honored by the API. + * + * ## Considerations for HTTP REST + * + * The HTTP kind of an update operation which uses a field mask must + * be set to PATCH instead of PUT in order to satisfy HTTP semantics + * (PUT must only be used for full updates). + * + * # JSON Encoding of Field Masks + * + * In JSON, a field mask is encoded as a single string where paths are + * separated by a comma. Fields name in each path are converted + * to/from lower-camel naming conventions. + * + * As an example, consider the following message declarations: + * + * message Profile { + * User user = 1; + * Photo photo = 2; + * } + * message User { + * string display_name = 1; + * string address = 2; + * } + * + * In proto a field mask for `Profile` may look as such: + * + * mask { + * paths: "user.display_name" + * paths: "photo" + * } + * + * In JSON, the same mask is represented as below: + * + * { + * mask: "user.displayName,photo" + * } + * + * # Field Masks and Oneof Fields + * + * Field masks treat fields in oneofs just as regular fields. Consider the + * following message: + * + * message SampleMessage { + * oneof test_oneof { + * string name = 4; + * SubMessage sub_message = 9; + * } + * } + * + * The field mask can be: + * + * mask { + * paths: "name" + * } + * + * Or: + * + * mask { + * paths: "sub_message" + * } + * + * Note that oneof type names ("test_oneof" in this case) cannot be used in + * paths. + * + * ## Field Mask Verification + * + * The implementation of any API method which has a FieldMask type field in the + * request should verify the included field paths, and return an + * `INVALID_ARGUMENT` error if any path is duplicated or unmappable. + **/ +@interface GPBFieldMask : GPBMessage + +/** The set of field mask paths. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *pathsArray; +/** The number of items in @c pathsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger pathsArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.m new file mode 100644 index 0000000..ff27318 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -0,0 +1,98 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/FieldMask.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBFieldMaskRoot + +@implementation GPBFieldMaskRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBFieldMaskRoot_FileDescriptor + +static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBFieldMask + +@implementation GPBFieldMask + +@dynamic pathsArray, pathsArray_Count; + +typedef struct GPBFieldMask__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *pathsArray; +} GPBFieldMask__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "pathsArray", + .dataTypeSpecific.className = NULL, + .number = GPBFieldMask_FieldNumber_PathsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] + rootClass:[GPBFieldMaskRoot class] + file:GPBFieldMaskRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBFieldMask__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.h new file mode 100644 index 0000000..e492395 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -0,0 +1,77 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBSourceContextRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBSourceContextRoot : GPBRootObject +@end + +#pragma mark - GPBSourceContext + +typedef GPB_ENUM(GPBSourceContext_FieldNumber) { + GPBSourceContext_FieldNumber_FileName = 1, +}; + +/** + * `SourceContext` represents information about the source of a + * protobuf element, like the file in which it is defined. + **/ +@interface GPBSourceContext : GPBMessage + +/** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.m new file mode 100644 index 0000000..c93871e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -0,0 +1,98 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/SourceContext.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBSourceContextRoot + +@implementation GPBSourceContextRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBSourceContextRoot_FileDescriptor + +static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBSourceContext + +@implementation GPBSourceContext + +@dynamic fileName; + +typedef struct GPBSourceContext__storage_ { + uint32_t _has_storage_[1]; + NSString *fileName; +} GPBSourceContext__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fileName", + .dataTypeSpecific.className = NULL, + .number = GPBSourceContext_FieldNumber_FileName, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] + rootClass:[GPBSourceContextRoot class] + file:GPBSourceContextRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBSourceContext__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.h new file mode 100644 index 0000000..fb20425 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.h @@ -0,0 +1,204 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBListValue; +@class GPBStruct; +@class GPBValue; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GPBNullValue + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + **/ +typedef GPB_ENUM(GPBNullValue) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Null value. */ + GPBNullValue_NullValue = 0, +}; + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBNullValue_IsValidValue(int32_t value); + +#pragma mark - GPBStructRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBStructRoot : GPBRootObject +@end + +#pragma mark - GPBStruct + +typedef GPB_ENUM(GPBStruct_FieldNumber) { + GPBStruct_FieldNumber_Fields = 1, +}; + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + **/ +@interface GPBStruct : GPBMessage + +/** Unordered map of dynamically typed values. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary *fields; +/** The number of items in @c fields without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger fields_Count; + +@end + +#pragma mark - GPBValue + +typedef GPB_ENUM(GPBValue_FieldNumber) { + GPBValue_FieldNumber_NullValue = 1, + GPBValue_FieldNumber_NumberValue = 2, + GPBValue_FieldNumber_StringValue = 3, + GPBValue_FieldNumber_BoolValue = 4, + GPBValue_FieldNumber_StructValue = 5, + GPBValue_FieldNumber_ListValue = 6, +}; + +typedef GPB_ENUM(GPBValue_Kind_OneOfCase) { + GPBValue_Kind_OneOfCase_GPBUnsetOneOfCase = 0, + GPBValue_Kind_OneOfCase_NullValue = 1, + GPBValue_Kind_OneOfCase_NumberValue = 2, + GPBValue_Kind_OneOfCase_StringValue = 3, + GPBValue_Kind_OneOfCase_BoolValue = 4, + GPBValue_Kind_OneOfCase_StructValue = 5, + GPBValue_Kind_OneOfCase_ListValue = 6, +}; + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of that + * variants, absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + **/ +@interface GPBValue : GPBMessage + +/** The kind of value. */ +@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase; + +/** Represents a null value. */ +@property(nonatomic, readwrite) GPBNullValue nullValue; + +/** Represents a double value. */ +@property(nonatomic, readwrite) double numberValue; + +/** Represents a string value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue; + +/** Represents a boolean value. */ +@property(nonatomic, readwrite) BOOL boolValue; + +/** Represents a structured value. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue; + +/** Represents a repeated `Value`. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue; + +@end + +/** + * Fetches the raw value of a @c GPBValue's @c nullValue property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBValue_NullValue_RawValue(GPBValue *message); +/** + * Sets the raw value of an @c GPBValue's @c nullValue property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value); + +/** + * Clears whatever value was set for the oneof 'kind'. + **/ +void GPBValue_ClearKindOneOfCase(GPBValue *message); + +#pragma mark - GPBListValue + +typedef GPB_ENUM(GPBListValue_FieldNumber) { + GPBListValue_FieldNumber_ValuesArray = 1, +}; + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + **/ +@interface GPBListValue : GPBMessage + +/** Repeated field of dynamically typed values. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valuesArray; +/** The number of items in @c valuesArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger valuesArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.m new file mode 100644 index 0000000..169a275 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Struct.pbobjc.m @@ -0,0 +1,302 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#import + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Struct.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +#pragma mark - GPBStructRoot + +@implementation GPBStructRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBStructRoot_FileDescriptor + +static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBNullValue + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "NullValue\000"; + static const int32_t values[] = { + GPBNullValue_NullValue, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBNullValue) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBNullValue_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBNullValue_IsValidValue(int32_t value__) { + switch (value__) { + case GPBNullValue_NullValue: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBStruct + +@implementation GPBStruct + +@dynamic fields, fields_Count; + +typedef struct GPBStruct__storage_ { + uint32_t _has_storage_[1]; + NSMutableDictionary *fields; +} GPBStruct__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fields", + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), + .number = GPBStruct_FieldNumber_Fields, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBStruct__storage_, fields), + .flags = GPBFieldMapKeyString, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStruct class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBStruct__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBValue + +@implementation GPBValue + +@dynamic kindOneOfCase; +@dynamic nullValue; +@dynamic numberValue; +@dynamic stringValue; +@dynamic boolValue; +@dynamic structValue; +@dynamic listValue; + +typedef struct GPBValue__storage_ { + uint32_t _has_storage_[2]; + GPBNullValue nullValue; + NSString *stringValue; + GPBStruct *structValue; + GPBListValue *listValue; + double numberValue; +} GPBValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "nullValue", + .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, + .number = GPBValue_FieldNumber_NullValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, nullValue), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "numberValue", + .dataTypeSpecific.className = NULL, + .number = GPBValue_FieldNumber_NumberValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, numberValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeDouble, + }, + { + .name = "stringValue", + .dataTypeSpecific.className = NULL, + .number = GPBValue_FieldNumber_StringValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, stringValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "boolValue", + .dataTypeSpecific.className = NULL, + .number = GPBValue_FieldNumber_BoolValue, + .hasIndex = -1, + .offset = 0, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "structValue", + .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct), + .number = GPBValue_FieldNumber_StructValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, structValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "listValue", + .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue), + .number = GPBValue_FieldNumber_ListValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, listValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + static const char *oneofs[] = { + "kind", + }; + [localDescriptor setupOneofs:oneofs + count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) + firstHasIndex:-1]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBValue_NullValue_RawValue(GPBValue *message) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +void GPBValue_ClearKindOneOfCase(GPBValue *message) { + GPBDescriptor *descriptor = [message descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBMaybeClearOneof(message, oneof, -1, 0); +} +#pragma mark - GPBListValue + +@implementation GPBListValue + +@dynamic valuesArray, valuesArray_Count; + +typedef struct GPBListValue__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *valuesArray; +} GPBListValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "valuesArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), + .number = GPBListValue_FieldNumber_ValuesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBListValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBListValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.h new file mode 100644 index 0000000..f6ea25c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -0,0 +1,165 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBTimestampRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBTimestampRoot : GPBRootObject +@end + +#pragma mark - GPBTimestamp + +typedef GPB_ENUM(GPBTimestamp_FieldNumber) { + GPBTimestamp_FieldNumber_Seconds = 1, + GPBTimestamp_FieldNumber_Nanos = 2, +}; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * + * Example 5: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) + * with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one + * can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + **/ +@interface GPBTimestamp : GPBMessage + +/** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + **/ +@property(nonatomic, readwrite) int64_t seconds; + +/** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + **/ +@property(nonatomic, readwrite) int32_t nanos; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.m new file mode 100644 index 0000000..b6393e3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -0,0 +1,109 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Timestamp.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBTimestampRoot + +@implementation GPBTimestampRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBTimestampRoot_FileDescriptor + +static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBTimestamp + +@implementation GPBTimestamp + +@dynamic seconds; +@dynamic nanos; + +typedef struct GPBTimestamp__storage_ { + uint32_t _has_storage_[1]; + int32_t nanos; + int64_t seconds; +} GPBTimestamp__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "seconds", + .dataTypeSpecific.className = NULL, + .number = GPBTimestamp_FieldNumber_Seconds, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + { + .name = "nanos", + .dataTypeSpecific.className = NULL, + .number = GPBTimestamp_FieldNumber_Nanos, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class] + rootClass:[GPBTimestampRoot class] + file:GPBTimestampRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBTimestamp__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.h new file mode 100644 index 0000000..e14d15d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.h @@ -0,0 +1,444 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBAny; +@class GPBEnumValue; +@class GPBField; +@class GPBOption; +@class GPBSourceContext; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GPBSyntax + +/** The syntax in which a protocol buffer element is defined. */ +typedef GPB_ENUM(GPBSyntax) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Syntax `proto2`. */ + GPBSyntax_SyntaxProto2 = 0, + + /** Syntax `proto3`. */ + GPBSyntax_SyntaxProto3 = 1, +}; + +GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBSyntax_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Kind + +/** Basic field types. */ +typedef GPB_ENUM(GPBField_Kind) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Field type unknown. */ + GPBField_Kind_TypeUnknown = 0, + + /** Field type double. */ + GPBField_Kind_TypeDouble = 1, + + /** Field type float. */ + GPBField_Kind_TypeFloat = 2, + + /** Field type int64. */ + GPBField_Kind_TypeInt64 = 3, + + /** Field type uint64. */ + GPBField_Kind_TypeUint64 = 4, + + /** Field type int32. */ + GPBField_Kind_TypeInt32 = 5, + + /** Field type fixed64. */ + GPBField_Kind_TypeFixed64 = 6, + + /** Field type fixed32. */ + GPBField_Kind_TypeFixed32 = 7, + + /** Field type bool. */ + GPBField_Kind_TypeBool = 8, + + /** Field type string. */ + GPBField_Kind_TypeString = 9, + + /** Field type group. Proto2 syntax only, and deprecated. */ + GPBField_Kind_TypeGroup = 10, + + /** Field type message. */ + GPBField_Kind_TypeMessage = 11, + + /** Field type bytes. */ + GPBField_Kind_TypeBytes = 12, + + /** Field type uint32. */ + GPBField_Kind_TypeUint32 = 13, + + /** Field type enum. */ + GPBField_Kind_TypeEnum = 14, + + /** Field type sfixed32. */ + GPBField_Kind_TypeSfixed32 = 15, + + /** Field type sfixed64. */ + GPBField_Kind_TypeSfixed64 = 16, + + /** Field type sint32. */ + GPBField_Kind_TypeSint32 = 17, + + /** Field type sint64. */ + GPBField_Kind_TypeSint64 = 18, +}; + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBField_Kind_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Cardinality + +/** Whether a field is optional, required, or repeated. */ +typedef GPB_ENUM(GPBField_Cardinality) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** For fields with unknown cardinality. */ + GPBField_Cardinality_CardinalityUnknown = 0, + + /** For optional fields. */ + GPBField_Cardinality_CardinalityOptional = 1, + + /** For required fields. Proto2 syntax only. */ + GPBField_Cardinality_CardinalityRequired = 2, + + /** For repeated fields. */ + GPBField_Cardinality_CardinalityRepeated = 3, +}; + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBField_Cardinality_IsValidValue(int32_t value); + +#pragma mark - GPBTypeRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBTypeRoot : GPBRootObject +@end + +#pragma mark - GPBType + +typedef GPB_ENUM(GPBType_FieldNumber) { + GPBType_FieldNumber_Name = 1, + GPBType_FieldNumber_FieldsArray = 2, + GPBType_FieldNumber_OneofsArray = 3, + GPBType_FieldNumber_OptionsArray = 4, + GPBType_FieldNumber_SourceContext = 5, + GPBType_FieldNumber_Syntax = 6, +}; + +/** + * A protocol buffer message type. + **/ +@interface GPBType : GPBMessage + +/** The fully qualified message name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** The list of fields. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldsArray; +/** The number of items in @c fieldsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger fieldsArray_Count; + +/** The list of types appearing in `oneof` definitions in this type. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray; +/** The number of items in @c oneofsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger oneofsArray_Count; + +/** The protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source context. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** The source syntax. */ +@property(nonatomic, readwrite) GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBType's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBType_Syntax_RawValue(GPBType *message); +/** + * Sets the raw value of an @c GPBType's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value); + +#pragma mark - GPBField + +typedef GPB_ENUM(GPBField_FieldNumber) { + GPBField_FieldNumber_Kind = 1, + GPBField_FieldNumber_Cardinality = 2, + GPBField_FieldNumber_Number = 3, + GPBField_FieldNumber_Name = 4, + GPBField_FieldNumber_TypeURL = 6, + GPBField_FieldNumber_OneofIndex = 7, + GPBField_FieldNumber_Packed = 8, + GPBField_FieldNumber_OptionsArray = 9, + GPBField_FieldNumber_JsonName = 10, + GPBField_FieldNumber_DefaultValue = 11, +}; + +/** + * A single field of a message type. + **/ +@interface GPBField : GPBMessage + +/** The field type. */ +@property(nonatomic, readwrite) GPBField_Kind kind; + +/** The field cardinality. */ +@property(nonatomic, readwrite) GPBField_Cardinality cardinality; + +/** The field number. */ +@property(nonatomic, readwrite) int32_t number; + +/** The field name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; + +/** + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + **/ +@property(nonatomic, readwrite) int32_t oneofIndex; + +/** Whether to use alternative packed wire representation. */ +@property(nonatomic, readwrite) BOOL packed; + +/** The protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The field JSON name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName; + +/** The string value of the default value of this field. Proto2 syntax only. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *defaultValue; + +@end + +/** + * Fetches the raw value of a @c GPBField's @c kind property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBField_Kind_RawValue(GPBField *message); +/** + * Sets the raw value of an @c GPBField's @c kind property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value); + +/** + * Fetches the raw value of a @c GPBField's @c cardinality property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBField_Cardinality_RawValue(GPBField *message); +/** + * Sets the raw value of an @c GPBField's @c cardinality property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value); + +#pragma mark - GPBEnum + +typedef GPB_ENUM(GPBEnum_FieldNumber) { + GPBEnum_FieldNumber_Name = 1, + GPBEnum_FieldNumber_EnumvalueArray = 2, + GPBEnum_FieldNumber_OptionsArray = 3, + GPBEnum_FieldNumber_SourceContext = 4, + GPBEnum_FieldNumber_Syntax = 5, +}; + +/** + * Enum type definition. + **/ +@interface GPBEnum : GPBMessage + +/** Enum type name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** Enum value definitions. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumvalueArray; +/** The number of items in @c enumvalueArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger enumvalueArray_Count; + +/** Protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source context. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** The source syntax. */ +@property(nonatomic, readwrite) GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBEnum's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBEnum_Syntax_RawValue(GPBEnum *message); +/** + * Sets the raw value of an @c GPBEnum's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value); + +#pragma mark - GPBEnumValue + +typedef GPB_ENUM(GPBEnumValue_FieldNumber) { + GPBEnumValue_FieldNumber_Name = 1, + GPBEnumValue_FieldNumber_Number = 2, + GPBEnumValue_FieldNumber_OptionsArray = 3, +}; + +/** + * Enum value definition. + **/ +@interface GPBEnumValue : GPBMessage + +/** Enum value name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** Enum value number. */ +@property(nonatomic, readwrite) int32_t number; + +/** Protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +@end + +#pragma mark - GPBOption + +typedef GPB_ENUM(GPBOption_FieldNumber) { + GPBOption_FieldNumber_Name = 1, + GPBOption_FieldNumber_Value = 2, +}; + +/** + * A protocol buffer option, which can be attached to a message, field, + * enumeration, etc. + **/ +@interface GPBOption : GPBMessage + +/** + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + **/ +@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.m new file mode 100644 index 0000000..6b88a4b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Type.pbobjc.m @@ -0,0 +1,716 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#import + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "google/protobuf/Type.pbobjc.h" + #import "google/protobuf/Any.pbobjc.h" + #import "google/protobuf/SourceContext.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBTypeRoot + +@implementation GPBTypeRoot + +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. + +@end + +#pragma mark - GPBTypeRoot_FileDescriptor + +static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBSyntax + +GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "SyntaxProto2\000SyntaxProto3\000"; + static const int32_t values[] = { + GPBSyntax_SyntaxProto2, + GPBSyntax_SyntaxProto3, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBSyntax_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBSyntax_IsValidValue(int32_t value__) { + switch (value__) { + case GPBSyntax_SyntaxProto2: + case GPBSyntax_SyntaxProto3: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBType + +@implementation GPBType + +@dynamic name; +@dynamic fieldsArray, fieldsArray_Count; +@dynamic oneofsArray, oneofsArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic hasSourceContext, sourceContext; +@dynamic syntax; + +typedef struct GPBType__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *fieldsArray; + NSMutableArray *oneofsArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBType__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBType_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBType__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "fieldsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBField), + .number = GPBType_FieldNumber_FieldsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, fieldsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "oneofsArray", + .dataTypeSpecific.className = NULL, + .number = GPBType_FieldNumber_OneofsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, oneofsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBType_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "sourceContext", + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .number = GPBType_FieldNumber_SourceContext, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBType__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBType_FieldNumber_Syntax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBType__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBType class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBType__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBType_Syntax_RawValue(GPBType *message) { + GPBDescriptor *descriptor = [GPBType descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) { + GPBDescriptor *descriptor = [GPBType descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBField + +@implementation GPBField + +@dynamic kind; +@dynamic cardinality; +@dynamic number; +@dynamic name; +@dynamic typeURL; +@dynamic oneofIndex; +@dynamic packed; +@dynamic optionsArray, optionsArray_Count; +@dynamic jsonName; +@dynamic defaultValue; + +typedef struct GPBField__storage_ { + uint32_t _has_storage_[1]; + GPBField_Kind kind; + GPBField_Cardinality cardinality; + int32_t number; + int32_t oneofIndex; + NSString *name; + NSString *typeURL; + NSMutableArray *optionsArray; + NSString *jsonName; + NSString *defaultValue; +} GPBField__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "kind", + .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, + .number = GPBField_FieldNumber_Kind, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBField__storage_, kind), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "cardinality", + .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, + .number = GPBField_FieldNumber_Cardinality, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBField__storage_, cardinality), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "number", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_Number, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBField__storage_, number), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_Name, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBField__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "typeURL", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_TypeURL, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .dataType = GPBDataTypeString, + }, + { + .name = "oneofIndex", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_OneofIndex, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "packed", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_Packed, + .hasIndex = 6, + .offset = 7, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBField_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBField__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "jsonName", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_JsonName, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GPBField__storage_, jsonName), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "defaultValue", + .dataTypeSpecific.className = NULL, + .number = GPBField_FieldNumber_DefaultValue, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBField class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBField__storage_) + flags:GPBDescriptorInitializationFlag_None]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\006\004\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBField_Kind_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +int32_t GPBField_Cardinality_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - Enum GPBField_Kind + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt" + "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type" + "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty" + "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000" + "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ" + "eSint64\000"; + static const int32_t values[] = { + GPBField_Kind_TypeUnknown, + GPBField_Kind_TypeDouble, + GPBField_Kind_TypeFloat, + GPBField_Kind_TypeInt64, + GPBField_Kind_TypeUint64, + GPBField_Kind_TypeInt32, + GPBField_Kind_TypeFixed64, + GPBField_Kind_TypeFixed32, + GPBField_Kind_TypeBool, + GPBField_Kind_TypeString, + GPBField_Kind_TypeGroup, + GPBField_Kind_TypeMessage, + GPBField_Kind_TypeBytes, + GPBField_Kind_TypeUint32, + GPBField_Kind_TypeEnum, + GPBField_Kind_TypeSfixed32, + GPBField_Kind_TypeSfixed64, + GPBField_Kind_TypeSint32, + GPBField_Kind_TypeSint64, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Kind_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Kind_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Kind_TypeUnknown: + case GPBField_Kind_TypeDouble: + case GPBField_Kind_TypeFloat: + case GPBField_Kind_TypeInt64: + case GPBField_Kind_TypeUint64: + case GPBField_Kind_TypeInt32: + case GPBField_Kind_TypeFixed64: + case GPBField_Kind_TypeFixed32: + case GPBField_Kind_TypeBool: + case GPBField_Kind_TypeString: + case GPBField_Kind_TypeGroup: + case GPBField_Kind_TypeMessage: + case GPBField_Kind_TypeBytes: + case GPBField_Kind_TypeUint32: + case GPBField_Kind_TypeEnum: + case GPBField_Kind_TypeSfixed32: + case GPBField_Kind_TypeSfixed64: + case GPBField_Kind_TypeSint32: + case GPBField_Kind_TypeSint64: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GPBField_Cardinality + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "CardinalityUnknown\000CardinalityOptional\000C" + "ardinalityRequired\000CardinalityRepeated\000"; + static const int32_t values[] = { + GPBField_Cardinality_CardinalityUnknown, + GPBField_Cardinality_CardinalityOptional, + GPBField_Cardinality_CardinalityRequired, + GPBField_Cardinality_CardinalityRepeated, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Cardinality_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Cardinality_CardinalityUnknown: + case GPBField_Cardinality_CardinalityOptional: + case GPBField_Cardinality_CardinalityRequired: + case GPBField_Cardinality_CardinalityRepeated: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBEnum + +@implementation GPBEnum + +@dynamic name; +@dynamic enumvalueArray, enumvalueArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic hasSourceContext, sourceContext; +@dynamic syntax; + +typedef struct GPBEnum__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *enumvalueArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBEnum__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBEnum_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBEnum__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "enumvalueArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue), + .number = GPBEnum_FieldNumber_EnumvalueArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnum__storage_, enumvalueArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBEnum_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnum__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "sourceContext", + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .number = GPBEnum_FieldNumber_SourceContext, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBEnum__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBEnum_FieldNumber_Syntax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnum class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBEnum__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) { + GPBDescriptor *descriptor = [GPBEnum descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; + return GPBGetMessageInt32Field(message, field); +} + +void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) { + GPBDescriptor *descriptor = [GPBEnum descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - GPBEnumValue + +@implementation GPBEnumValue + +@dynamic name; +@dynamic number; +@dynamic optionsArray, optionsArray_Count; + +typedef struct GPBEnumValue__storage_ { + uint32_t _has_storage_[1]; + int32_t number; + NSString *name; + NSMutableArray *optionsArray; +} GPBEnumValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBEnumValue_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "number", + .dataTypeSpecific.className = NULL, + .number = GPBEnumValue_FieldNumber_Number, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + { + .name = "optionsArray", + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .number = GPBEnumValue_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBEnumValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBOption + +@implementation GPBOption + +@dynamic name; +@dynamic hasValue, value; + +typedef struct GPBOption__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + GPBAny *value; +} GPBOption__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.className = NULL, + .number = GPBOption_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBOption__storage_, name), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.className = GPBStringifySymbol(GPBAny), + .number = GPBOption_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBOption__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBOption class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBOption__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.h new file mode 100644 index 0000000..0411e1e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -0,0 +1,219 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBWrappersRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +@interface GPBWrappersRoot : GPBRootObject +@end + +#pragma mark - GPBDoubleValue + +typedef GPB_ENUM(GPBDoubleValue_FieldNumber) { + GPBDoubleValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + **/ +@interface GPBDoubleValue : GPBMessage + +/** The double value. */ +@property(nonatomic, readwrite) double value; + +@end + +#pragma mark - GPBFloatValue + +typedef GPB_ENUM(GPBFloatValue_FieldNumber) { + GPBFloatValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + **/ +@interface GPBFloatValue : GPBMessage + +/** The float value. */ +@property(nonatomic, readwrite) float value; + +@end + +#pragma mark - GPBInt64Value + +typedef GPB_ENUM(GPBInt64Value_FieldNumber) { + GPBInt64Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + **/ +@interface GPBInt64Value : GPBMessage + +/** The int64 value. */ +@property(nonatomic, readwrite) int64_t value; + +@end + +#pragma mark - GPBUInt64Value + +typedef GPB_ENUM(GPBUInt64Value_FieldNumber) { + GPBUInt64Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + **/ +@interface GPBUInt64Value : GPBMessage + +/** The uint64 value. */ +@property(nonatomic, readwrite) uint64_t value; + +@end + +#pragma mark - GPBInt32Value + +typedef GPB_ENUM(GPBInt32Value_FieldNumber) { + GPBInt32Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + **/ +@interface GPBInt32Value : GPBMessage + +/** The int32 value. */ +@property(nonatomic, readwrite) int32_t value; + +@end + +#pragma mark - GPBUInt32Value + +typedef GPB_ENUM(GPBUInt32Value_FieldNumber) { + GPBUInt32Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + **/ +@interface GPBUInt32Value : GPBMessage + +/** The uint32 value. */ +@property(nonatomic, readwrite) uint32_t value; + +@end + +#pragma mark - GPBBoolValue + +typedef GPB_ENUM(GPBBoolValue_FieldNumber) { + GPBBoolValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + **/ +@interface GPBBoolValue : GPBMessage + +/** The bool value. */ +@property(nonatomic, readwrite) BOOL value; + +@end + +#pragma mark - GPBStringValue + +typedef GPB_ENUM(GPBStringValue_FieldNumber) { + GPBStringValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + **/ +@interface GPBStringValue : GPBMessage + +/** The string value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; + +@end + +#pragma mark - GPBBytesValue + +typedef GPB_ENUM(GPBBytesValue_FieldNumber) { + GPBBytesValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + **/ +@interface GPBBytesValue : GPBMessage + +/** The bytes value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.m new file mode 100644 index 0000000..0a163fa --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Protobuf/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -0,0 +1,457 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "google/protobuf/Wrappers.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBWrappersRoot + +@implementation GPBWrappersRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBWrappersRoot_FileDescriptor + +static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDoubleValue + +@implementation GPBDoubleValue + +@dynamic value; + +typedef struct GPBDoubleValue__storage_ { + uint32_t _has_storage_[1]; + double value; +} GPBDoubleValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBDoubleValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeDouble, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBDoubleValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBFloatValue + +@implementation GPBFloatValue + +@dynamic value; + +typedef struct GPBFloatValue__storage_ { + uint32_t _has_storage_[1]; + float value; +} GPBFloatValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBFloatValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeFloat, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBFloatValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt64Value + +@implementation GPBInt64Value + +@dynamic value; + +typedef struct GPBInt64Value__storage_ { + uint32_t _has_storage_[1]; + int64_t value; +} GPBInt64Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBInt64Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBInt64Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt64Value + +@implementation GPBUInt64Value + +@dynamic value; + +typedef struct GPBUInt64Value__storage_ { + uint32_t _has_storage_[1]; + uint64_t value; +} GPBUInt64Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBUInt64Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBUInt64Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt32Value + +@implementation GPBInt32Value + +@dynamic value; + +typedef struct GPBInt32Value__storage_ { + uint32_t _has_storage_[1]; + int32_t value; +} GPBInt32Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBInt32Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBInt32Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt32Value + +@implementation GPBUInt32Value + +@dynamic value; + +typedef struct GPBUInt32Value__storage_ { + uint32_t _has_storage_[1]; + uint32_t value; +} GPBUInt32Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBUInt32Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBUInt32Value__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBBoolValue + +@implementation GPBBoolValue + +@dynamic value; + +typedef struct GPBBoolValue__storage_ { + uint32_t _has_storage_[1]; +} GPBBoolValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBBoolValue_FieldNumber_Value, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBBoolValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBStringValue + +@implementation GPBStringValue + +@dynamic value; + +typedef struct GPBStringValue__storage_ { + uint32_t _has_storage_[1]; + NSString *value; +} GPBStringValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBStringValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBStringValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBStringValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBBytesValue + +@implementation GPBBytesValue + +@dynamic value; + +typedef struct GPBBytesValue__storage_ { + uint32_t _has_storage_[1]; + NSData *value; +} GPBBytesValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.className = NULL, + .number = GPBBytesValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBBytesValue__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/LICENSE new file mode 100644 index 0000000..49640fd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 Shiny Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/README.md new file mode 100644 index 0000000..70cf14a --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/README.md @@ -0,0 +1,61 @@ +## Simulator Status Magic + +Modify the iOS Simulator so that it has a perfect status bar, then run your app and take perfect screenshots every time. The modifications made are designed to match the images you see on the Apple site and are as follows: + +* 9:41 AM is displayed for the time. +* The battery is full and shows 100%. +* 5 bars of cellular signal and full WiFi bars are displayed. +* Tue Jan 9 is displayed for the date (iPad only) + +### How do I use it? + +* Clone this repository. +* Open SimulatorStatusMagic.xcodeproj with Xcode 6 (or above). +* Run the app target `SimulatorStatusMagic` (not `SimulatorStatusMagiciOS`) on whichever simulator type you would like to modify (it works with every device). +* Once the app launches, press the only button on the screen :) +* That's it, you're done! Now just run your app and take screenshots. + +### How do I remove the customisations? + +Run the app again and click "Restore Default Status Bar". Resetting the iOS Simulator using the normal menu option also works. + +### I have a script to take my screenshots, can I automate this? + +Yes! SimulatorStatusMagic is available via [CocoaPods](http://cocoapods.org), [Carthage](https://github.com/Carthage/Carthage) and as a standalone source release. [Installation instructions](https://github.com/shinydevelopment/SimulatorStatusMagic/blob/master/INSTALLATION.md) are available. + +It is recommended to **only** include `SDStatusBarManager` in your debug configuration so that the code is **never** included in release builds. When you want to apply a perfect status bar, call `[[SDStatusBarManager sharedInstance] enableOverrides]`. To restore the standard status bar, call `[[SDStatusBarManager sharedInstance] disableOverrides]`. + +### What about automation of the sample app? + +If you'd prefer to automate the app itself to automatically enable or disable the overrides, this can be done with environment variables. + +Run with: + +```` +SIMULATOR_STATUS_MAGIC_OVERRIDES = enable +```` + +or + +```` +SIMULATOR_STATUS_MAGIC_OVERRIDES = disable +```` + +The overrides will be automatically enabled or disabled on launch. + +### Does this work on device? + +No. The status bar server is blocked on devices. However, macOS includes the facility to include a perfect status bar when recording your device screen with QuickTime ([Read more](https://appadvice.com/appnn/2014/08/quicktime-in-os-x-yosemite-reveals-that-apple-cares-about-status-bars)). + +### How does this work? + +The best idea is to check [the source code](https://github.com/shinydevelopment/SimulatorStatusMagic/blob/master/SDStatusBarManager/SDStatusBarManager.m) which should get you started with how it works :) + +## Contributing + +We'd love contributions and even have some suggestions for things that might need working on: + +* Found a bug? If you report it with a pull request attached then you get a gold star :) +* ~~Non-English language support. We'd love it to work with more languages.~~ Now works with every language! + +However, the scope of this project is intentionally limited. We're not planning to add options to this to allow ultimate customisation of the status bar. It's intended to do just one job really well, change the status bar to match [Apple's marketing materials](http://www.apple.com/ios/). diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarManager.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarManager.h new file mode 100644 index 0000000..23433c3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarManager.h @@ -0,0 +1,61 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import + +typedef NS_ENUM(NSInteger, SDStatusBarManagerBluetoothState) +{ + SDStatusBarManagerBluetoothHidden = 0, + SDStatusBarManagerBluetoothVisibleDimmed, + SDStatusBarManagerBluetoothVisibleConnected +}; + +typedef NS_ENUM(NSInteger, SDStatusBarManagerNetworkType) +{ + SDStatusBarManagerNetworkTypeWiFi = 0, + SDStatusBarManagerNetworkTypeGPRS, + SDStatusBarManagerNetworkTypeEdge, + SDStatusBarManagerNetworkType3G, + SDStatusBarManagerNetworkType4G, + SDStatusBarManagerNetworkTypeLTE +}; + +@interface SDStatusBarManager : NSObject + +@property (copy, nonatomic) NSString *carrierName; +@property (copy, nonatomic) NSString *timeString; +@property (copy, nonatomic) NSString *dateString; +@property (assign, nonatomic, readonly) BOOL usingOverrides; +@property (assign, nonatomic) SDStatusBarManagerBluetoothState bluetoothState; +@property (assign, nonatomic) SDStatusBarManagerNetworkType networkType; +@property (assign, nonatomic) BOOL batteryDetailEnabled; +@property (assign, nonatomic) BOOL iPadDateEnabled; +@property (assign, nonatomic) BOOL iPadGsmSignalEnabled; + +- (void)enableOverrides; +- (void)disableOverrides; + ++ (SDStatusBarManager *)sharedInstance; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarManager.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarManager.m new file mode 100644 index 0000000..2a64ac1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarManager.m @@ -0,0 +1,263 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarManager.h" +#import "SDStatusBarOverriderPre8_3.h" +#import "SDStatusBarOverriderPost8_3.h" +#import "SDStatusBarOverriderPost9_0.h" +#import "SDStatusBarOverriderPost9_3.h" +#import "SDStatusBarOverriderPost10_0.h" +#import "SDStatusBarOverriderPost10_3.h" +#import "SDStatusBarOverriderPost11_0.h" +#import "SDStatusBarOverriderPost12_0.h" + +static NSString * const SDStatusBarManagerUsingOverridesKey = @"using_overrides"; +static NSString * const SDStatusBarManagerBluetoothStateKey = @"bluetooth_state"; +static NSString * const SDStatusBarManagerNetworkTypeKey = @"network_type"; +static NSString * const SDStatusBarManagerCarrierNameKey = @"carrier_name"; +static NSString * const SDStatusBarManagerTimeStringKey = @"time_string"; +static NSString * const SDStatusBarManagerDateStringKey = @"date_string"; + +@interface SDStatusBarManager () + +@property (nonatomic, strong) NSUserDefaults *userDefaults; +@property (nonatomic, strong) id overrider; + +@end + +@implementation SDStatusBarManager + +- (instancetype)init +{ + self = [super init]; + if (self) { + // Set any defaults for the status bar + self.batteryDetailEnabled = YES; + self.iPadDateEnabled = YES; + self.iPadGsmSignalEnabled = NO; + } + return self; +} + +- (void)enableOverrides +{ + self.usingOverrides = YES; + + self.overrider.timeString = [self localizedTimeString]; + self.overrider.dateString = [self localizedDateString]; + self.overrider.carrierName = self.carrierName; + self.overrider.bluetoothEnabled = self.bluetoothState != SDStatusBarManagerBluetoothHidden; + self.overrider.bluetoothConnected = self.bluetoothState == SDStatusBarManagerBluetoothVisibleConnected; + self.overrider.batteryDetailEnabled = self.batteryDetailEnabled; + self.overrider.networkType = self.networkType; + self.overrider.iPadDateEnabled = self.iPadDateEnabled; + self.overrider.iPadGsmSignalEnabled = self.iPadGsmSignalEnabled; + + [self.overrider enableOverrides]; +} + +- (void)disableOverrides +{ + self.usingOverrides = NO; + + [self.overrider disableOverrides]; +} + +#pragma mark Properties +- (BOOL)usingOverrides +{ + return [self.userDefaults boolForKey:SDStatusBarManagerUsingOverridesKey]; +} + +- (void)setUsingOverrides:(BOOL)usingOverrides +{ + [self.userDefaults setBool:usingOverrides forKey:SDStatusBarManagerUsingOverridesKey]; +} + +- (void)setBluetoothState:(SDStatusBarManagerBluetoothState)bluetoothState +{ + if (self.bluetoothState == bluetoothState) return; + + [self.userDefaults setValue:@(bluetoothState) forKey:SDStatusBarManagerBluetoothStateKey]; + + if (self.usingOverrides) { + [self enableOverrides]; + } +} + +- (SDStatusBarManagerBluetoothState)bluetoothState +{ + return [[self.userDefaults valueForKey:SDStatusBarManagerBluetoothStateKey] integerValue]; +} + +- (void)setNetworkType:(SDStatusBarManagerNetworkType)networkType +{ + if (self.networkType == networkType) return; + + [self.userDefaults setValue:@(networkType) forKey:SDStatusBarManagerNetworkTypeKey]; + + if (self.usingOverrides) { + [self enableOverrides]; + } +} + +- (SDStatusBarManagerNetworkType)networkType +{ + return [[self.userDefaults valueForKey:SDStatusBarManagerNetworkTypeKey] integerValue]; +} + +- (void)setCarrierName:(NSString *)carrierName +{ + if ([self.carrierName isEqualToString:carrierName]) return; + + [self.userDefaults setObject:carrierName forKey:SDStatusBarManagerCarrierNameKey]; + + if (self.usingOverrides) { + [self enableOverrides]; + } +} + +- (NSString *)carrierName +{ + return [self.userDefaults valueForKey:SDStatusBarManagerCarrierNameKey]; +} + +- (void)setTimeString:(NSString *)timeString +{ + if ([self.timeString isEqualToString:timeString]) return; + + [self.userDefaults setObject:timeString forKey:SDStatusBarManagerTimeStringKey]; + + if (self.usingOverrides) { + [self enableOverrides]; + } +} + +- (NSString *)timeString +{ + return [self.userDefaults valueForKey:SDStatusBarManagerTimeStringKey]; +} + +- (void)setDateString:(NSString *)dateString { + if ([self.dateString isEqualToString:dateString]) return; + + [self.userDefaults setObject:dateString forKey:SDStatusBarManagerDateStringKey]; + + if (self.usingOverrides) { + [self enableOverrides]; + } +} + +- (NSString *)dateString +{ + return [self.userDefaults valueForKey:SDStatusBarManagerDateStringKey]; +} + +- (NSUserDefaults *)userDefaults +{ + if (!_userDefaults) { + _userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.shinydevelopment.SDStatusBarManager"]; + } + return _userDefaults; +} + ++ (id)overriderForSystemVersion:(NSString *)systemVersion +{ + id overrider = nil; + NSProcessInfo *pi = [NSProcessInfo processInfo]; + if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 12, 0, 0 }]) { + overrider = [SDStatusBarOverriderPost12_0 new]; + } else if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 11, 0, 0 }]) { + overrider = [SDStatusBarOverriderPost11_0 new]; + } else if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 10, 3, 0 }]) { + overrider = [SDStatusBarOverriderPost10_3 new]; + } else if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 10, 0, 0 }]) { + overrider = [SDStatusBarOverriderPost10_0 new]; + } else if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 9, 3, 0 }]) { + overrider = [SDStatusBarOverriderPost9_3 new]; + } else if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 9, 0, 0 }]) { + overrider = [SDStatusBarOverriderPost9_0 new]; + } else if ([pi isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 8, 3, 0 }]) { + overrider = [SDStatusBarOverriderPost8_3 new]; + } else { + overrider = [SDStatusBarOverriderPre8_3 new]; + } + return overrider; +} + +- (id)overrider +{ + if (!_overrider) { + NSString *systemVersion = [[UIDevice currentDevice] systemVersion]; + _overrider = [SDStatusBarManager overriderForSystemVersion:systemVersion]; + } + return _overrider; +} + +#pragma mark Date helper +- (NSString *)localizedTimeString +{ + if (self.timeString.length > 0) { + return self.timeString; + } + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateStyle = NSDateFormatterNoStyle; + formatter.timeStyle = NSDateFormatterShortStyle; + + NSDateComponents *components = [[NSCalendar currentCalendar] components: NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]]; + components.hour = 9; + components.minute = 41; + + return [formatter stringFromDate:[[NSCalendar currentCalendar] dateFromComponents:components]]; +} + +- (NSString *)localizedDateString +{ + if (self.dateString.length > 0) { + return self.dateString; + } + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = [[NSDateFormatter dateFormatFromTemplate:@"EEE MMM d" options:0 locale:NSLocale.currentLocale] stringByReplacingOccurrencesOfString:@"," withString:@""]; + + NSDateComponents *components = [[NSCalendar currentCalendar] components: NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:[NSDate date]]; + components.day = 9; + components.month = 1; + components.year = 2007; + + return [formatter stringFromDate:[[NSCalendar currentCalendar] dateFromComponents:components]]; +} + +#pragma mark Singleton instance ++ (SDStatusBarManager *)sharedInstance +{ + static dispatch_once_t predicate = 0; + __strong static id sharedObject = nil; + dispatch_once(&predicate, ^{ sharedObject = [[self alloc] init]; }); + return sharedObject; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverrider.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverrider.h new file mode 100644 index 0000000..49cab24 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverrider.h @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import + +#import "SDStatusBarManager.h" + +@protocol SDStatusBarOverrider + +@property (copy, nonatomic) NSString *timeString; +@property (copy, nonatomic) NSString *dateString; +@property (copy, nonatomic) NSString* carrierName; + +@property (assign, nonatomic) BOOL bluetoothEnabled; +@property (assign, nonatomic) BOOL bluetoothConnected; +@property (assign, nonatomic) BOOL batteryDetailEnabled; +@property (assign, nonatomic) SDStatusBarManagerNetworkType networkType; +@property (assign, nonatomic) BOOL iPadDateEnabled; +@property (assign, nonatomic) BOOL iPadGsmSignalEnabled; + +- (void)enableOverrides; +- (void)disableOverrides; + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_0.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_0.h new file mode 100644 index 0000000..f5aa243 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_0.h @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPost10_0 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_0.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_0.m new file mode 100644 index 0000000..75977ac --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_0.m @@ -0,0 +1,269 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverriderPost10_0.h" + +typedef NS_ENUM(int, StatusBarItem10_0) { + DoNotDisturb = 1, + // 2 + SignalStrengthBars = 3, + // 4 + // 5 + // 6 + // 7 + // 8 + BatteryDetail = 9, + // 10 + // 11 + Bluetooth = 12, + // 13 + Alarms = 14, + // 15 + // 16 + // 17 + RotationLock = 18, + // 19 + // 20 + // 21 + // 22 + // 23 + // 24 + // 25 + // 26 + // 27 + // 28 + // 29 + // 30 + // 31 + // 32 + // 33 +}; + +typedef NS_ENUM(unsigned int, BatteryState) { + BatteryStateUnplugged = 0 +}; + +typedef struct { + _Bool itemIsEnabled[34]; + char timeString[64]; + int gsmSignalStrengthRaw; + int gsmSignalStrengthBars; + char serviceString[100]; + char serviceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode:1; + unsigned int slowActivity:1; + unsigned int syncActivity:1; + char activityDisplayId[256]; + unsigned int bluetoothConnected:1; + unsigned int displayRawGSMSignal:1; + unsigned int displayRawWifiSignal:1; + unsigned int locationIconType:1; + unsigned int quietModeInactive:1; + unsigned int tetheringConnectionCount; + unsigned int batterySaverModeActive:1; + unsigned int deviceIsRTL:1; + unsigned int lock:1; + char breadcrumbTitle[256]; + char breadcrumbSecondaryTitle[256]; + char personName[100]; + char returnToAppBundleIdentifier[100]; + unsigned int electronicTollCollectionAvailable:1; + unsigned int wifiLinkWarning:1; +} StatusBarRawData; + +typedef struct { + _Bool overrideItemIsEnabled[34]; + unsigned int overrideTimeString:1; + unsigned int overrideGsmSignalStrengthRaw:1; + unsigned int overrideGsmSignalStrengthBars:1; + unsigned int overrideServiceString:1; + unsigned int overrideServiceImages:2; + unsigned int overrideOperatorDirectory:1; + unsigned int overrideServiceContentType:1; + unsigned int overrideWifiSignalStrengthRaw:1; + unsigned int overrideWifiSignalStrengthBars:1; + unsigned int overrideDataNetworkType:1; + unsigned int disallowsCellularDataNetworkTypes:1; + unsigned int overrideBatteryCapacity:1; + unsigned int overrideBatteryState:1; + unsigned int overrideBatteryDetailString:1; + unsigned int overrideBluetoothBatteryCapacity:1; + unsigned int overrideThermalColor:1; + unsigned int overrideSlowActivity:1; + unsigned int overrideActivityDisplayId:1; + unsigned int overrideBluetoothConnected:1; + unsigned int overrideBreadcrumb:1; + unsigned int overrideLock; + unsigned int overrideDisplayRawGSMSignal:1; + unsigned int overrideDisplayRawWifiSignal:1; + unsigned int overridePersonName:1; + unsigned int overrideWifiLinkWarning:1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServer; + +// http://localhost:10000/protocols/UIStatusBarServerClient.h (commented some methods, and added structs) +/* Generated by RuntimeBrowser. + */ + +@protocol UIStatusBarServerClient + +@required + +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStatusBarData:(const StatusBarRawData *)data withActions:(int)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStyleOverrides:(int)arg2; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveGlowAnimationState:(bool)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveDoubleHeightStatusString:(NSString *)arg2 forStyle:(long long)arg3; + +@end + +// http://localhost:10000/classes/UIStatusBarServer.h (commented some methods, and added structs) +/* Generated by RuntimeBrowser. + */ + +@interface UIStatusBarServer : NSObject + +@property (nonatomic, strong) id statusBar; + ++ (void)postStatusBarOverrideData:(StatusBarOverrideData *)arg1; ++ (void)permanentizeStatusBarOverrideData; ++ (const StatusBarRawData *)getStatusBarData; ++ (StatusBarOverrideData *)getStatusBarOverrideData; + +@end + +@implementation SDStatusBarOverriderPost10_0 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + overrides->overrideTimeString = 1; + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->overrideItemIsEnabled[SignalStrengthBars] = 1; + overrides->values.itemIsEnabled[SignalStrengthBars] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + overrides->overrideServiceString = 1; + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery: 100% and unplugged + overrides->overrideItemIsEnabled[BatteryDetail] = YES; + overrides->values.itemIsEnabled[BatteryDetail] = YES; + overrides->overrideBatteryCapacity = YES; + overrides->values.batteryCapacity = 100; + overrides->overrideBatteryState = YES; + overrides->values.batteryState = BatteryStateUnplugged; + overrides->overrideBatteryDetailString = YES; + NSString *batteryDetailString = self.batteryDetailEnabled ? [NSString stringWithFormat:@"%@%%", @(overrides->values.batteryCapacity)] : @" "; // Setting this to an empty string will not work, it needs to be a @" " + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->overrideItemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + overrides->values.itemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Remove the @" " used to trick the battery percentage into not showing, if used + if (!self.batteryDetailEnabled) { + batteryDetailString = @""; + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove all overrides that use the array of bools + bzero(overrides->overrideItemIsEnabled, sizeof(overrides->overrideItemIsEnabled)); + bzero(overrides->values.itemIsEnabled, sizeof(overrides->values.itemIsEnabled)); + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryCapacity = 0; + overrides->overrideBatteryState = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_3.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_3.h new file mode 100644 index 0000000..1974970 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_3.h @@ -0,0 +1,14 @@ +// +// SDStatusBarOverriderPost10_3.h +// SimulatorStatusMagic +// +// Created by Craig Siemens on 2017-03-27. +// Copyright © 2017 Shiny Development. All rights reserved. +// + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPost10_3 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_3.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_3.m new file mode 100644 index 0000000..0a77e37 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost10_3.m @@ -0,0 +1,246 @@ +// +// SDStatusBarOverriderPost10_3.m +// SimulatorStatusMagic +// +// Created by Craig Siemens on 2017-03-27. +// Copyright © 2017 Shiny Development. All rights reserved. +// + +#import +#import "SDStatusBarOverriderPost10_3.h" + +typedef NS_ENUM(int, StatusBarItem10_0) { + // 0 + DoNotDisturb = 1, + // 2 + SignalStrengthBars = 3, + // 4 + // 5 + // 6 + // 7 + // 8 + BatteryDetail = 9, + // 10 + // 11 + Bluetooth = 12, + // 13 + Alarms = 14, + // 15 + // 16 + // 17 + RotationLock = 18, + // 19 + // 20 + // 21 + // 22 + // 23 + // 24 + // 25 + // 26 + // 27 + // 28 + // 29 + // 30 + // 31 + // 32 + // 33 + // 34 +}; + +typedef NS_ENUM(unsigned int, BatteryState) { + BatteryStateUnplugged = 0 +}; + +typedef struct { + bool itemIsEnabled[35]; + char timeString[64]; + int gsmSignalStrengthRaw; + int gsmSignalStrengthBars; + char serviceString[100]; + char serviceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode : 1; + unsigned int slowActivity : 1; + unsigned int syncActivity : 1; + char activityDisplayId[256]; + unsigned int bluetoothConnected : 1; + unsigned int displayRawGSMSignal : 1; + unsigned int displayRawWifiSignal : 1; + unsigned int locationIconType : 1; + unsigned int quietModeInactive : 1; + unsigned int tetheringConnectionCount; + unsigned int batterySaverModeActive : 1; + unsigned int deviceIsRTL : 1; + unsigned int lock : 1; + char breadcrumbTitle[256]; + char breadcrumbSecondaryTitle[256]; + char personName[100]; +// or returnToAppBundleIdentifier + unsigned int electronicTollCollectionAvailable : 1; + unsigned int wifiLinkWarning : 1; +} StatusBarRawData; + +typedef struct { + bool overrideItemIsEnabled[35]; + unsigned int overrideTimeString : 1; + unsigned int overrideGsmSignalStrengthRaw : 1; + unsigned int overrideGsmSignalStrengthBars : 1; + unsigned int overrideServiceString : 1; + unsigned int overrideServiceImages : 2; + unsigned int overrideOperatorDirectory : 1; + unsigned int overrideServiceContentType : 1; + unsigned int overrideWifiSignalStrengthRaw : 1; + unsigned int overrideWifiSignalStrengthBars : 1; + unsigned int overrideDataNetworkType : 1; + unsigned int disallowsCellularDataNetworkTypes : 1; + unsigned int overrideBatteryCapacity : 1; + unsigned int overrideBatteryState : 1; + unsigned int overrideBatteryDetailString : 1; + unsigned int overrideBluetoothBatteryCapacity : 1; + unsigned int overrideThermalColor : 1; + unsigned int overrideSlowActivity : 1; + unsigned int overrideActivityDisplayId : 1; + unsigned int overrideBluetoothConnected : 1; + unsigned int overrideBreadcrumb : 1; + unsigned int overrideLock; + unsigned int overrideDisplayRawGSMSignal : 1; + unsigned int overrideDisplayRawWifiSignal : 1; + unsigned int overridePersonName : 1; + unsigned int overrideWifiLinkWarning : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServer; + +@protocol UIStatusBarServerClient + +@required + +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveDoubleHeightStatusString:(NSString *)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveGlowAnimationState:(bool)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStatusBarData:(const StatusBarRawData *)data withActions:(int)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStyleOverrides:(int)arg2; + +@end + +@interface UIStatusBarServer : NSObject + +@property (nonatomic, strong) id statusBar; + ++ (void)postStatusBarOverrideData:(StatusBarOverrideData *)arg1; ++ (void)permanentizeStatusBarOverrideData; ++ (const StatusBarRawData *)getStatusBarData; ++ (StatusBarOverrideData *)getStatusBarOverrideData; + +@end + +@implementation SDStatusBarOverriderPost10_3 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides { + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + overrides->overrideTimeString = 1; + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->overrideItemIsEnabled[SignalStrengthBars] = 1; + overrides->values.itemIsEnabled[SignalStrengthBars] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + overrides->overrideServiceString = 1; + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery: 100% and unplugged + overrides->overrideItemIsEnabled[BatteryDetail] = YES; + overrides->values.itemIsEnabled[BatteryDetail] = YES; + overrides->overrideBatteryCapacity = YES; + overrides->values.batteryCapacity = 100; + overrides->overrideBatteryState = YES; + overrides->values.batteryState = BatteryStateUnplugged; + overrides->overrideBatteryDetailString = YES; + NSString *batteryDetailString = self.batteryDetailEnabled ? [NSString stringWithFormat:@"%@%%", @(overrides->values.batteryCapacity)] : @" "; +// Setting this to an empty string will not work, it needs to be a @" " + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->overrideItemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + overrides->values.itemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Remove the @" " used to trick the battery percentage into not showing, if used + if (!self.batteryDetailEnabled) { + batteryDetailString = @""; + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides { + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove all overrides that use the array of bools + bzero(overrides->overrideItemIsEnabled, sizeof(overrides->overrideItemIsEnabled)); + bzero(overrides->values.itemIsEnabled, sizeof(overrides->values.itemIsEnabled)); + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryCapacity = 0; + overrides->overrideBatteryState = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost11_0.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost11_0.h new file mode 100644 index 0000000..92c3021 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost11_0.h @@ -0,0 +1,14 @@ +// +// SDStatusBarOverriderPost11_0.h +// SimulatorStatusMagic +// +// Created by Craig Siemens on 2017-07-11. +// Copyright © 2017 Shiny Development. All rights reserved. +// + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPost11_0 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost11_0.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost11_0.m new file mode 100644 index 0000000..a9d7b9c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost11_0.m @@ -0,0 +1,249 @@ +// +// SDStatusBarOverriderPost11_0.m +// SimulatorStatusMagic +// +// Created by Craig Siemens on 2017-07-11. +// Copyright © 2017 Shiny Development. All rights reserved. +// + +#import +#import "SDStatusBarOverriderPost11_0.h" + +typedef NS_ENUM(int, StatusBarItem) { + // 0 + DoNotDisturb = 1, + // 2 + SignalStrengthBars = 3, + // 4 + // 5 + // 6 + // 7 + // 8 + BatteryDetail = 9, + // 10 + // 11 + Bluetooth = 12, + // 13 + Alarms = 14, + // 15 + // 16 + // 17 + RotationLock = 18, + // 19 + // 20 + // 21 + // 22 + // 23 + // 24 + // 25 + // 26 + // 27 + // 28 + // 29 + // 30 + // 31 + // 32 + // 33 + // 34 +}; + +typedef NS_ENUM(unsigned int, BatteryState) { + BatteryStateUnplugged = 0 +}; + +typedef struct { + bool itemIsEnabled[35]; + char timeString[64]; + char shortTimeString[64]; + int gsmSignalStrengthRaw; + int gsmSignalStrengthBars; + char serviceString[100]; + char serviceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode : 1; + unsigned int slowActivity : 1; + unsigned int syncActivity : 1; + char activityDisplayId[256]; + unsigned int bluetoothConnected : 1; + unsigned int displayRawGSMSignal : 1; + unsigned int displayRawWifiSignal : 1; + unsigned int locationIconType : 1; + unsigned int quietModeInactive : 1; + unsigned int tetheringConnectionCount; + unsigned int batterySaverModeActive : 1; + unsigned int deviceIsRTL : 1; + unsigned int lock : 1; + char breadcrumbTitle[256]; + char breadcrumbSecondaryTitle[256]; + char personName[100]; + unsigned int electronicTollCollectionAvailable : 1; + unsigned int wifiLinkWarning : 1; + unsigned int wifiSearching : 1; + double backgroundActivityDisplayStartDate; + unsigned int shouldShowEmergencyOnlyStatus : 1; +} StatusBarRawData; + +typedef struct { + bool overrideItemIsEnabled[35]; + unsigned int overrideTimeString : 1; + unsigned int overrideGsmSignalStrengthRaw : 1; + unsigned int overrideGsmSignalStrengthBars : 1; + unsigned int overrideServiceString : 1; + unsigned int overrideServiceImages : 2; + unsigned int overrideOperatorDirectory : 1; + unsigned int overrideServiceContentType : 1; + unsigned int overrideWifiSignalStrengthRaw : 1; + unsigned int overrideWifiSignalStrengthBars : 1; + unsigned int overrideDataNetworkType : 1; + unsigned int disallowsCellularDataNetworkTypes : 1; + unsigned int overrideBatteryCapacity : 1; + unsigned int overrideBatteryState : 1; + unsigned int overrideBatteryDetailString : 1; + unsigned int overrideBluetoothBatteryCapacity : 1; + unsigned int overrideThermalColor : 1; + unsigned int overrideSlowActivity : 1; + unsigned int overrideActivityDisplayId : 1; + unsigned int overrideBluetoothConnected : 1; + unsigned int overrideBreadcrumb : 1; + unsigned int overrideLock; + unsigned int overrideDisplayRawGSMSignal : 1; + unsigned int overrideDisplayRawWifiSignal : 1; + unsigned int overridePersonName : 1; + unsigned int overrideWifiLinkWarning : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServer; + +@protocol UIStatusBarServerClient + +@required + +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveDoubleHeightStatusString:(NSString *)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveGlowAnimationState:(bool)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStatusBarData:(const StatusBarRawData *)arg2 withActions:(int)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStyleOverrides:(int)arg2; + +@end + +@interface UIStatusBarServer : NSObject + +@property (nonatomic, strong) id statusBar; + ++ (void)postStatusBarOverrideData:(StatusBarOverrideData *)arg1; ++ (void)permanentizeStatusBarOverrideData; ++ (const StatusBarRawData *)getStatusBarData; ++ (StatusBarOverrideData *)getStatusBarOverrideData; + +@end + +@implementation SDStatusBarOverriderPost11_0 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides { + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + overrides->overrideTimeString = 1; + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->overrideItemIsEnabled[SignalStrengthBars] = 1; + overrides->values.itemIsEnabled[SignalStrengthBars] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + overrides->overrideServiceString = 1; + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery: 100% and unplugged + overrides->overrideItemIsEnabled[BatteryDetail] = YES; + overrides->values.itemIsEnabled[BatteryDetail] = YES; + overrides->overrideBatteryCapacity = YES; + overrides->values.batteryCapacity = 100; + overrides->overrideBatteryState = YES; + overrides->values.batteryState = BatteryStateUnplugged; + overrides->overrideBatteryDetailString = YES; + NSString *batteryDetailString = self.batteryDetailEnabled ? [NSString stringWithFormat:@"%@%%", @(overrides->values.batteryCapacity)] : @" "; + // Setting this to an empty string will not work, it needs to be a @" " + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->overrideItemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + overrides->values.itemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Remove the @" " used to trick the battery percentage into not showing, if used + if (!self.batteryDetailEnabled) { + batteryDetailString = @""; + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides { + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove all overrides that use the array of bools + bzero(overrides->overrideItemIsEnabled, sizeof(overrides->overrideItemIsEnabled)); + bzero(overrides->values.itemIsEnabled, sizeof(overrides->values.itemIsEnabled)); + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryCapacity = 0; + overrides->overrideBatteryState = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost12_0.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost12_0.h new file mode 100644 index 0000000..33847d0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost12_0.h @@ -0,0 +1,18 @@ +// +// SDStatusBarOverriderPost12_0.h +// SimulatorStatusMagic +// +// Created by Scott Talbot on 6/6/18. +// Copyright © 2018 Shiny Development. All rights reserved. +// + +#import +#import "SDStatusBarOverrider.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SDStatusBarOverriderPost12_0 : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost12_0.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost12_0.m new file mode 100644 index 0000000..6231688 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost12_0.m @@ -0,0 +1,289 @@ +// +// SDStatusBarOverriderPost12_0.m +// SimulatorStatusMagic +// +// Created by Scott Talbot on 6/6/18. +// Copyright © 2018 Shiny Development. All rights reserved. +// + +#import +#import "SDStatusBarOverriderPost12_0.h" + +typedef NS_ENUM(int, StatusBarItem) { + // 0 + dateStringIpad = 1, + // 2 + // 3 + SignalStrengthBars = 4, + SecondarySignalStrengthBars = 5, + SignalStrengthBarsVisibleOnIpad = 6, + // 7 + // 8 + // 9 + // 10 + // 11 + // 12 + BatteryDetail = 13, + // 14 + // 15 + Bluetooth = 16, + // 17 + // 18 + // 19 + // 20 + // 21 + // 22 + // 23 + // 24 + // 25 + // 26 + // 27 + // 28 + // 29 + // 30 + // 31 + // 32 + // 33 + // 34 + // 35 + // 36 + // 37 + // 38 + // 39 + // 40 +}; + +typedef NS_ENUM(unsigned int, BatteryState) { + BatteryStateUnplugged = 0 +}; + +typedef struct { + bool itemIsEnabled[41]; + char timeString[64]; + char shortTimeString[64]; + char dateString[256]; + int gsmSignalStrengthRaw; + int secondaryGsmSignalStrengthRaw; + int gsmSignalStrengthBars; + int secondaryGsmSignalStrengthBars; + char serviceString[100]; + char secondaryServiceString[100]; + char serviceCrossfadeString[100]; + char secondaryServiceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + unsigned int secondaryServiceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + unsigned int secondaryDataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode : 1; + unsigned int slowActivity : 1; + unsigned int syncActivity : 1; + char activityDisplayId[256]; + unsigned int bluetoothConnected : 1; + unsigned int displayRawGSMSignal : 1; + unsigned int displayRawWifiSignal : 1; + unsigned int locationIconType : 1; + unsigned int quietModeInactive : 1; + unsigned int tetheringConnectionCount; + unsigned int batterySaverModeActive : 1; + unsigned int deviceIsRTL : 1; + unsigned int lock : 1; + char breadcrumbTitle[256]; + char breadcrumbSecondaryTitle[256]; + char personName[100]; + unsigned int electronicTollCollectionAvailable : 1; + unsigned int wifiLinkWarning : 1; + unsigned int wifiSearching : 1; + double backgroundActivityDisplayStartDate; + unsigned int shouldShowEmergencyOnlyStatus : 1; + unsigned int secondaryCellularConfigured : 1; + char primaryServiceBadgeString[100]; + char secondaryServiceBadgeString[100]; +} StatusBarRawData; + +typedef struct { + bool overrideItemIsEnabled[41]; + unsigned int overrideTimeString : 1; + unsigned int overrideDateString : 1; + unsigned int overrideGsmSignalStrengthRaw : 1; + unsigned int overrideSecondaryGsmSignalStrengthRaw : 1; + unsigned int overrideGsmSignalStrengthBars : 1; + unsigned int overrideSecondaryGsmSignalStrengthBars : 1; + unsigned int overrideServiceString : 1; + unsigned int overrideSecondaryServiceString : 1; + unsigned int overrideServiceImages : 2; + unsigned int overrideOperatorDirectory : 1; + unsigned int overrideServiceContentType : 1; + unsigned int overrideSecondaryServiceContentType : 1; + unsigned int overrideWifiSignalStrengthRaw : 1; + unsigned int overrideWifiSignalStrengthBars : 1; + unsigned int overrideDataNetworkType : 1; + unsigned int overrideSecondaryDataNetworkType : 1; + unsigned int disallowsCellularDataNetworkTypes : 1; + unsigned int overrideBatteryCapacity : 1; + unsigned int overrideBatteryState : 1; + unsigned int overrideBatteryDetailString : 1; + unsigned int overrideBluetoothBatteryCapacity : 1; + unsigned int overrideThermalColor : 1; + unsigned int overrideSlowActivity : 1; + unsigned int overrideActivityDisplayId : 1; + unsigned int overrideBluetoothConnected : 1; + unsigned int overrideBreadcrumb : 1; + unsigned int overrideLock; + unsigned int overrideDisplayRawGSMSignal : 1; + unsigned int overrideDisplayRawWifiSignal : 1; + unsigned int overridePersonName : 1; + unsigned int overrideWifiLinkWarning : 1; + unsigned int overrideSecondaryCellularConfigured : 1; + unsigned int overridePrimaryServiceBadgeString : 1; + unsigned int overrideSecondaryServiceBadgeString : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServer; + +@protocol UIStatusBarServerClient + +@required + +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveDoubleHeightStatusString:(NSString *)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveGlowAnimationState:(bool)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStatusBarData:(const StatusBarRawData *)arg2 withActions:(int)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStyleOverrides:(int)arg2; + +@end + +@interface UIStatusBarServer : NSObject + +@property (nonatomic, strong) id statusBar; + ++ (void)postStatusBarOverrideData:(StatusBarOverrideData *)arg1; ++ (void)permanentizeStatusBarOverrideData; ++ (StatusBarOverrideData *)getStatusBarOverrideData; + +@end + +@implementation SDStatusBarOverriderPost12_0 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides { + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + overrides->overrideTimeString = 1; + + // Set Tue Jan 9 in current localization + strcpy(overrides->values.dateString, [self.dateString cStringUsingEncoding:NSUTF8StringEncoding]); + overrides->overrideDateString = 1; + + // Show / Hide date on iPad + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) { + overrides->overrideItemIsEnabled[dateStringIpad] = 1; + overrides->values.itemIsEnabled[dateStringIpad] = self.iPadDateEnabled ? 1 : 0; + } + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->overrideItemIsEnabled[SignalStrengthBars] = 1; + overrides->values.itemIsEnabled[SignalStrengthBars] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + // Enable / Disable GSM signal bars on iPad + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) { + if (self.iPadGsmSignalEnabled) { + overrides->overrideItemIsEnabled[SignalStrengthBars] = 1; + overrides->values.itemIsEnabled[SignalStrengthBars] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } else { + overrides->overrideItemIsEnabled[SignalStrengthBarsVisibleOnIpad] = 1; + overrides->values.itemIsEnabled[SignalStrengthBars] = 0; + } + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + overrides->overrideServiceString = 1; + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery: 100% and unplugged + overrides->overrideItemIsEnabled[BatteryDetail] = YES; + overrides->values.itemIsEnabled[BatteryDetail] = self.batteryDetailEnabled; + overrides->overrideBatteryCapacity = YES; + overrides->values.batteryCapacity = 100; + overrides->overrideBatteryState = YES; + overrides->values.batteryState = BatteryStateUnplugged; + overrides->overrideBatteryDetailString = YES; + NSString *batteryDetailString = [NSString stringWithFormat:@"%@%%", @(overrides->values.batteryCapacity)]; + strcpy(overrides->values.batteryDetailString, [batteryDetailString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->overrideItemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + overrides->values.itemIsEnabled[Bluetooth] = !!self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides { + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove all overrides that use the array of bools + bzero(overrides->overrideItemIsEnabled, sizeof(overrides->overrideItemIsEnabled)); + bzero(overrides->values.itemIsEnabled, sizeof(overrides->values.itemIsEnabled)); + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideDateString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryCapacity = 0; + overrides->overrideBatteryState = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost8_3.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost8_3.h new file mode 100644 index 0000000..27dcfef --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost8_3.h @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPost8_3 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost8_3.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost8_3.m new file mode 100644 index 0000000..b27c779 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost8_3.m @@ -0,0 +1,212 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverriderPost8_3.h" + +/* Generated by RuntimeBrowser. + Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/UIKit.framework/UIKit + */ + +typedef struct { + char boolitemIsEnabled[26]; + char timeString[64]; + int gsmSignalStrengthRaw; + int gsmSignalStrengthBars; + char serviceString[100]; + char serviceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode : 1; + unsigned int slowActivity : 1; + unsigned int syncActivity : 1; + BOOL activityDisplayId[256]; + unsigned int bluetoothConnected : 1; + unsigned int displayRawGSMSignal : 1; + unsigned int displayRawWifiSignal : 1; + unsigned int locationIconType : 1; + unsigned int quietModeInactive : 1; + unsigned int tetheringConnectionCount; +} StatusBarRawData; + +typedef struct { + char booloverrideItemIsEnabled[26]; + unsigned int overrideTimeString : 1; + unsigned int overrideGsmSignalStrengthRaw : 1; + unsigned int overrideGsmSignalStrengthBars : 1; + unsigned int overrideServiceString : 1; + unsigned int overrideServiceImages : 2; + unsigned int overrideOperatorDirectory : 1; + unsigned int overrideServiceContentType : 1; + unsigned int overrideWifiSignalStrengthRaw : 1; + unsigned int overrideWifiSignalStrengthBars : 1; + unsigned int overrideDataNetworkType : 1; + unsigned int disallowsCellularDataNetworkTypes : 1; + unsigned int overrideBatteryCapacity : 1; + unsigned int overrideBatteryState : 1; + unsigned int overrideBatteryDetailString : 1; + unsigned int overrideBluetoothBatteryCapacity : 1; + unsigned int overrideThermalColor : 1; + unsigned int overrideSlowActivity : 1; + unsigned int overrideActivityDisplayId : 1; + unsigned int overrideBluetoothConnected : 1; + unsigned int overrideDisplayRawGSMSignal : 1; + unsigned int overrideDisplayRawWifiSignal : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServerClient; + +@interface UIStatusBarServer : NSObject { + UIStatusBarServerClient *_statusBar; + struct __CFRunLoopSource { } *_source; +} + +@property(retain) UIStatusBarServerClient * statusBar; + ++ (unsigned int)_serverPort; ++ (void)runServer; ++ (id)getDoubleHeightStatusStringForStyle:(long long)arg1; ++ (bool)getGlowAnimationStateForStyle:(long long)arg1; ++ (int)getStyleOverrides; ++ (StatusBarOverrideData *)getStatusBarOverrideData; ++ (const StatusBarRawData*)getStatusBarData; ++ (void)permanentizeStatusBarOverrideData; ++ (void)postStatusBarOverrideData:(StatusBarOverrideData*)arg1; ++ (void)postStatusBarData:(const StatusBarRawData*)arg1 withActions:(int)arg2; ++ (unsigned int)_publisherPort; ++ (double)getGlowAnimationEndTimeForStyle:(long long)arg1; ++ (void)removeStatusBarItem:(int)arg1; ++ (void)addStatusBarItem:(int)arg1; ++ (void)postDoubleHeightStatusString:(id)arg1 forStyle:(long long)arg2; ++ (void)postGlowAnimationState:(bool)arg1 forStyle:(long long)arg2; ++ (void)removeStyleOverrides:(int)arg1; ++ (void)addStyleOverrides:(int)arg1; +@end + +@implementation SDStatusBarOverriderPost8_3 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + overrides->overrideTimeString = 1; + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->booloverrideItemIsEnabled[3] = 1; + overrides->values.boolitemIsEnabled[3] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery + overrides->booloverrideItemIsEnabled[8] = 1; + overrides->values.boolitemIsEnabled[8] = 1; + overrides->overrideBatteryDetailString = 1; + strcpy(overrides->values.batteryDetailString, [self.batteryDetailEnabled ? @"100%" : @" " cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->booloverrideItemIsEnabled[11] = self.bluetoothEnabled; + overrides->values.boolitemIsEnabled[11] = self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // if battery detail was not required, then it was set to one space @" ", so let's correct it here in case bluetooth icon comes after it + if (!self.batteryDetailEnabled) { + strcpy(overrides->values.batteryDetailString, [@"" cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Remove all overrides that use the array of bools + for (int i = 0; i < 26; i++) { + overrides->booloverrideItemIsEnabled[i] = 0; + overrides->values.boolitemIsEnabled[i] = 0; + } + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_0.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_0.h new file mode 100644 index 0000000..0f767f4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_0.h @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPost9_0 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_0.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_0.m new file mode 100644 index 0000000..58b8a3c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_0.m @@ -0,0 +1,213 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverriderPost9_0.h" + +/* Generated by RuntimeBrowser. + Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/UIKit.framework/UIKit + */ + +typedef struct { + char boolitemIsEnabled[27]; + char timeString[64]; + int gsmSignalStrengthRaw; + int gsmSignalStrengthBars; + char serviceString[100]; + char serviceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode : 1; + unsigned int slowActivity : 1; + unsigned int syncActivity : 1; + BOOL activityDisplayId[256]; + unsigned int bluetoothConnected : 1; + unsigned int displayRawGSMSignal : 1; + unsigned int displayRawWifiSignal : 1; + unsigned int locationIconType : 1; + unsigned int quietModeInactive : 1; + unsigned int tetheringConnectionCount; + unsigned int unknownOption : 1; +} StatusBarRawData; + +typedef struct { + char booloverrideItemIsEnabled[27]; + unsigned int overrideTimeString : 1; + unsigned int overrideGsmSignalStrengthRaw : 1; + unsigned int overrideGsmSignalStrengthBars : 1; + unsigned int overrideServiceString : 1; + unsigned int overrideServiceImages : 2; + unsigned int overrideOperatorDirectory : 1; + unsigned int overrideServiceContentType : 1; + unsigned int overrideWifiSignalStrengthRaw : 1; + unsigned int overrideWifiSignalStrengthBars : 1; + unsigned int overrideDataNetworkType : 1; + unsigned int disallowsCellularDataNetworkTypes : 1; + unsigned int overrideBatteryCapacity : 1; + unsigned int overrideBatteryState : 1; + unsigned int overrideBatteryDetailString : 1; + unsigned int overrideBluetoothBatteryCapacity : 1; + unsigned int overrideThermalColor : 1; + unsigned int overrideSlowActivity : 1; + unsigned int overrideActivityDisplayId : 1; + unsigned int overrideBluetoothConnected : 1; + unsigned int overrideDisplayRawGSMSignal : 1; + unsigned int overrideDisplayRawWifiSignal : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServerClient; + +@interface UIStatusBarServer : NSObject { + UIStatusBarServerClient *_statusBar; + struct __CFRunLoopSource { } *_source; +} + +@property(retain) UIStatusBarServerClient * statusBar; + ++ (unsigned int)_serverPort; ++ (void)runServer; ++ (id)getDoubleHeightStatusStringForStyle:(long long)arg1; ++ (bool)getGlowAnimationStateForStyle:(long long)arg1; ++ (int)getStyleOverrides; ++ (StatusBarOverrideData *)getStatusBarOverrideData; ++ (const StatusBarRawData*)getStatusBarData; ++ (void)permanentizeStatusBarOverrideData; ++ (void)postStatusBarOverrideData:(StatusBarOverrideData*)arg1; ++ (void)postStatusBarData:(const StatusBarRawData*)arg1 withActions:(int)arg2; ++ (unsigned int)_publisherPort; ++ (double)getGlowAnimationEndTimeForStyle:(long long)arg1; ++ (void)removeStatusBarItem:(int)arg1; ++ (void)addStatusBarItem:(int)arg1; ++ (void)postDoubleHeightStatusString:(id)arg1 forStyle:(long long)arg2; ++ (void)postGlowAnimationState:(bool)arg1 forStyle:(long long)arg2; ++ (void)removeStyleOverrides:(int)arg1; ++ (void)addStyleOverrides:(int)arg1; +@end + +@implementation SDStatusBarOverriderPost9_0 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + overrides->overrideTimeString = 1; + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->booloverrideItemIsEnabled[3] = 1; + overrides->values.boolitemIsEnabled[3] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery + overrides->booloverrideItemIsEnabled[8] = 1; + overrides->values.boolitemIsEnabled[8] = 1; + overrides->overrideBatteryDetailString = 1; + strcpy(overrides->values.batteryDetailString, [self.batteryDetailEnabled? @"100%" : @" " cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->booloverrideItemIsEnabled[11] = self.bluetoothEnabled; + overrides->values.boolitemIsEnabled[11] = self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // if battery detail was not required, then it was set to one space @" ", so let's correct it here in case bluetooth icon comes after it + if (!self.batteryDetailEnabled) { + strcpy(overrides->values.batteryDetailString, [@"" cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Remove all overrides that use the array of bools + for (int i = 0; i < 27; i++) { + overrides->booloverrideItemIsEnabled[i] = 0; + overrides->values.boolitemIsEnabled[i] = 0; + } + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_3.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_3.h new file mode 100644 index 0000000..76c995e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_3.h @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPost9_3 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_3.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_3.m new file mode 100644 index 0000000..7876a9c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPost9_3.m @@ -0,0 +1,257 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverriderPost9_3.h" + +enum { + ItemIsEnabledDoNotDisturb = 1, + ItemIsEnabledAirplaneIcon, + ItemIsEnabledGsmSignalStrengthShowDots, + // 4 : unknown, + ItemIsEnabledGsmSignalStrengthRawValue, + ItemIsEnabledBatteryDetailString = 9, + ItemIsEnabledBatteryBluetoothIcon = 12, +} ItemIsEnabledIndexes; + +@class UIStatusBarServer; + +// http://localhost:10000/protocols/UIStatusBarServerClient.h +/* Generated by RuntimeBrowser. + */ + +@protocol UIStatusBarServerClient + +@required + +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveDoubleHeightStatusString:(NSString *)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveGlowAnimationState:(bool)arg2 forStyle:(long long)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStatusBarData:(const struct { bool x1[29]; BOOL x2[64]; int x3; int x4; BOOL x5[100]; BOOL x6[100]; BOOL x7[2][100]; BOOL x8[1024]; unsigned int x9; int x10; int x11; unsigned int x12; int x13; unsigned int x14; BOOL x15[150]; int x16; int x17; unsigned int x18 : 1; unsigned int x19 : 1; unsigned int x20 : 1; BOOL x21[256]; unsigned int x22 : 1; unsigned int x23 : 1; unsigned int x24 : 1; unsigned int x25 : 1; unsigned int x26 : 1; unsigned int x27; unsigned int x28 : 1; unsigned int x29 : 1; BOOL x30[256]; BOOL x31[256]; BOOL x32[100]; }*)arg2 withActions:(int)arg3; +- (void)statusBarServer:(UIStatusBarServer *)arg1 didReceiveStyleOverrides:(int)arg2; + +@end + +// http://localhost:10000/classes/UIStatusBarServer.h (commented some methods, and added structs) +/* Generated by RuntimeBrowser. + */ + +typedef struct { + bool boolitemIsEnabled[29];//x_25_1_1[29]; // boolitemIsEnabled + char timeString[64];//x_25_1_2[64]; // timeString + int x_25_1_3; // gsmSignalStrengthRaw + int gsmSignalStrengthBars;//x_25_1_4; // gsmSignalStrengthBars + char serviceString[100]; // serviceString + char serviceCrossfadeString[100]; + char x_25_1_7[2][100]; + char x_25_1_8[1024]; + unsigned int x_25_1_9; + int x_25_1_10; + int x_25_1_11; + unsigned int dataNetworkType; + int x_25_1_13; + unsigned int x_25_1_14; + char batteryDetailString[150];//x_25_1_15[150]; + int x_25_1_16; + int x_25_1_17; + unsigned int x_25_1_18 : 1; + unsigned int x_25_1_19 : 1; + unsigned int x_25_1_20 : 1; + char x_25_1_21[256]; + unsigned int bluetoothConnected: 1;//x_25_1_22 : 1; + unsigned int x_25_1_23 : 1; + unsigned int x_25_1_24 : 1; + unsigned int x_25_1_25 : 1; + unsigned int x_25_1_26 : 1; + unsigned int x_25_1_27; + unsigned int x_25_1_28 : 1; + unsigned int x_25_1_29 : 1; + char x_25_1_30[256]; + char x_25_1_31[256]; + char x_25_1_32[100]; +} StatusBarRawData; + +typedef struct { + bool booloverrideItemIsEnabled[29];//x1[29]; + unsigned int overrideTimeString : 1; // x2 : 1; // overrideTimeString + unsigned int x3 : 1; // overrideGsmSignalStrengthRaw + unsigned int overrideGsmSignalStrengthBars: 1;//x4 : 1; // overrideGsmSignalStrengthBars + unsigned int overrideServiceString: 1;//x5 : 1; // overrideServiceString + unsigned int x6 : 2; // overrideServiceImages + unsigned int x7 : 1; // overrideOperatorDirectory + unsigned int x8 : 1; // overrideServiceContentType + unsigned int x9 : 1; // overrideWifiSignalStrengthRaw + unsigned int x10 : 1; // overrideWifiSignalStrengthBars + unsigned int overrideDataNetworkType : 1; // overrideDataNetworkType + unsigned int x12 : 1; // disallowsCellularDataNetworkTypes + unsigned int x13 : 1; // overrideBatteryCapacity + unsigned int x14 : 1; // overrideBatteryState + unsigned int overrideBatteryDetailString: 1;//x15 : 1; // overrideBatteryDetailString + unsigned int x16 : 1; // overrideBluetoothBatteryCapacity + unsigned int x17 : 1; // overrideThermalColor + unsigned int x18 : 1; // overrideSlowActivity + unsigned int x19 : 1; // overrideActivityDisplayId + unsigned int overrideBluetoothConnected: 1; //x20 : 1; // overrideBluetoothConnected + unsigned int x21 : 1; // overrideDisplayRawGSMSignal + unsigned int x22 : 1; // overrideDisplayRawWifiSignal + unsigned int x23 : 1; + unsigned int x24 : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@interface UIStatusBarServer : NSObject { + struct __CFRunLoopSource { } * _source; + id _statusBar; +} + +//@property (nonatomic, retain) *statusBar; +@property (nonatomic, retain) id statusBar; + ++ (unsigned int)_publisherPort; ++ (unsigned int)_serverPort; ++ (void)addStatusBarItem:(int)arg1; ++ (void)addStyleOverrides:(int)arg1; ++ (id)getDoubleHeightStatusStringForStyle:(long long)arg1; ++ (double)getGlowAnimationEndTimeForStyle:(long long)arg1; ++ (bool)getGlowAnimationStateForStyle:(long long)arg1; +//+ (const struct { bool x1[29]; BOOL x2[64]; int x3; int x4; BOOL x5[100]; BOOL x6[100]; BOOL x7[2][100]; BOOL x8[1024]; unsigned int x9; int x10; int x11; unsigned int x12; int x13; unsigned int x14; BOOL x15[150]; int x16; int x17; unsigned int x18 : 1; unsigned int x19 : 1; unsigned int x20 : 1; BOOL x21[256]; unsigned int x22 : 1; unsigned int x23 : 1; unsigned int x24 : 1; unsigned int x25 : 1; unsigned int x26 : 1; unsigned int x27; unsigned int x28 : 1; unsigned int x29 : 1; BOOL x30[256]; BOOL x31[256]; BOOL x32[100]; }*)getStatusBarData; ++ (const StatusBarRawData *)getStatusBarData; +//+ (struct { bool x1[29]; unsigned int x2 : 1; unsigned int x3 : 1; unsigned int x4 : 1; unsigned int x5 : 1; unsigned int x6 : 2; unsigned int x7 : 1; unsigned int x8 : 1; unsigned int x9 : 1; unsigned int x10 : 1; unsigned int x11 : 1; unsigned int x12 : 1; unsigned int x13 : 1; unsigned int x14 : 1; unsigned int x15 : 1; unsigned int x16 : 1; unsigned int x17 : 1; unsigned int x18 : 1; unsigned int x19 : 1; unsigned int x20 : 1; unsigned int x21 : 1; unsigned int x22 : 1; unsigned int x23 : 1; unsigned int x24 : 1; struct { bool x_25_1_1[29]; BOOL x_25_1_2[64]; int x_25_1_3; int x_25_1_4; BOOL x_25_1_5[100]; BOOL x_25_1_6[100]; BOOL x_25_1_7[2][100]; BOOL x_25_1_8[1024]; unsigned int x_25_1_9; int x_25_1_10; int x_25_1_11; unsigned int x_25_1_12; int x_25_1_13; unsigned int x_25_1_14; BOOL x_25_1_15[150]; int x_25_1_16; int x_25_1_17; unsigned int x_25_1_18 : 1; unsigned int x_25_1_19 : 1; unsigned int x_25_1_20 : 1; BOOL x_25_1_21[256]; unsigned int x_25_1_22 : 1; unsigned int x_25_1_23 : 1; unsigned int x_25_1_24 : 1; unsigned int x_25_1_25 : 1; unsigned int x_25_1_26 : 1; unsigned int x_25_1_27; unsigned int x_25_1_28 : 1; unsigned int x_25_1_29 : 1; BOOL x_25_1_30[256]; BOOL x_25_1_31[256]; BOOL x_25_1_32[100]; } x25; }*)getStatusBarOverrideData; ++ (StatusBarOverrideData *)getStatusBarOverrideData; ++ (int)getStyleOverrides; ++ (void)permanentizeStatusBarOverrideData; ++ (void)postDoubleHeightStatusString:(id)arg1 forStyle:(long long)arg2; ++ (void)postGlowAnimationState:(bool)arg1 forStyle:(long long)arg2; +//+ (void)postStatusBarData:(const struct { bool x1[29]; BOOL x2[64]; int x3; int x4; BOOL x5[100]; BOOL x6[100]; BOOL x7[2][100]; BOOL x8[1024]; unsigned int x9; int x10; int x11; unsigned int x12; int x13; unsigned int x14; BOOL x15[150]; int x16; int x17; unsigned int x18 : 1; unsigned int x19 : 1; unsigned int x20 : 1; BOOL x21[256]; unsigned int x22 : 1; unsigned int x23 : 1; unsigned int x24 : 1; unsigned int x25 : 1; unsigned int x26 : 1; unsigned int x27; unsigned int x28 : 1; unsigned int x29 : 1; BOOL x30[256]; BOOL x31[256]; BOOL x32[100]; }*)arg1 withActions:(int)arg2; ++ (void)postStatusBarData:(const StatusBarRawData *)arg1 withActions:(int)arg2; +//+ (void)postStatusBarOverrideData:(struct { bool x1[29]; unsigned int x2 : 1; unsigned int x3 : 1; unsigned int x4 : 1; unsigned int x5 : 1; unsigned int x6 : 2; unsigned int x7 : 1; unsigned int x8 : 1; unsigned int x9 : 1; unsigned int x10 : 1; unsigned int x11 : 1; unsigned int x12 : 1; unsigned int x13 : 1; unsigned int x14 : 1; unsigned int x15 : 1; unsigned int x16 : 1; unsigned int x17 : 1; unsigned int x18 : 1; unsigned int x19 : 1; unsigned int x20 : 1; unsigned int x21 : 1; unsigned int x22 : 1; unsigned int x23 : 1; unsigned int x24 : 1; struct { bool x_25_1_1[29]; BOOL x_25_1_2[64]; int x_25_1_3; int x_25_1_4; BOOL x_25_1_5[100]; BOOL x_25_1_6[100]; BOOL x_25_1_7[2][100]; BOOL x_25_1_8[1024]; unsigned int x_25_1_9; int x_25_1_10; int x_25_1_11; unsigned int x_25_1_12; int x_25_1_13; unsigned int x_25_1_14; BOOL x_25_1_15[150]; int x_25_1_16; int x_25_1_17; unsigned int x_25_1_18 : 1; unsigned int x_25_1_19 : 1; unsigned int x_25_1_20 : 1; BOOL x_25_1_21[256]; unsigned int x_25_1_22 : 1; unsigned int x_25_1_23 : 1; unsigned int x_25_1_24 : 1; unsigned int x_25_1_25 : 1; unsigned int x_25_1_26 : 1; unsigned int x_25_1_27; unsigned int x_25_1_28 : 1; unsigned int x_25_1_29 : 1; BOOL x_25_1_30[256]; BOOL x_25_1_31[256]; BOOL x_25_1_32[100]; } x25; }*)arg1; ++ (void)postStatusBarOverrideData:(StatusBarOverrideData *)arg1; ++ (void)removeStatusBarItem:(int)arg1; ++ (void)removeStyleOverrides:(int)arg1; ++ (void)runServer; + +//- (void).cxx_destruct; +- (void)_receivedDoubleHeightStatus:(const char *)arg1 forStyle:(long long)arg2; +- (void)_receivedGlowAnimationState:(bool)arg1 forStyle:(long long)arg2; +- (void)_receivedStatusBarData:(struct { bool x1[29]; BOOL x2[64]; int x3; int x4; BOOL x5[100]; BOOL x6[100]; BOOL x7[2][100]; BOOL x8[1024]; unsigned int x9; int x10; int x11; unsigned int x12; int x13; unsigned int x14; BOOL x15[150]; int x16; int x17; unsigned int x18 : 1; unsigned int x19 : 1; unsigned int x20 : 1; BOOL x21[256]; unsigned int x22 : 1; unsigned int x23 : 1; unsigned int x24 : 1; unsigned int x25 : 1; unsigned int x26 : 1; unsigned int x27; unsigned int x28 : 1; unsigned int x29 : 1; BOOL x30[256]; BOOL x31[256]; BOOL x32[100]; }*)arg1 actions:(int)arg2; +- (void)_receivedStyleOverrides:(int)arg1; +- (void)dealloc; +- (id)initWithStatusBar:(id)arg1; +//- (void)setStatusBar:(id)arg1; +//- (id)statusBar; + +@end + +@implementation SDStatusBarOverriderPost9_3 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + overrides->overrideTimeString = 1; + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->booloverrideItemIsEnabled[ItemIsEnabledGsmSignalStrengthShowDots] = 1; + overrides->values.boolitemIsEnabled[ItemIsEnabledGsmSignalStrengthShowDots] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery + overrides->booloverrideItemIsEnabled[ItemIsEnabledBatteryDetailString] = 1; + overrides->values.boolitemIsEnabled[ItemIsEnabledBatteryDetailString] = 1; + overrides->overrideBatteryDetailString = 1; + strcpy(overrides->values.batteryDetailString, [self.batteryDetailEnabled? @"100%" : @" " cStringUsingEncoding:NSUTF8StringEncoding]); // Setting this to an empty string will not work, it needs to be a @" " + + // Bluetooth + overrides->booloverrideItemIsEnabled[ItemIsEnabledBatteryBluetoothIcon] = self.bluetoothEnabled; + overrides->values.boolitemIsEnabled[ItemIsEnabledBatteryBluetoothIcon] = self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Remove the @" " used to trick the battery percentage into not showing, if used + if (!self.batteryDetailEnabled) { + strcpy(overrides->values.batteryDetailString, [@"" cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Remove all overrides that use the array of bools + memset(overrides->booloverrideItemIsEnabled, 0, sizeof(overrides->booloverrideItemIsEnabled)); + memset(overrides->values.boolitemIsEnabled, 0, sizeof(overrides->values.boolitemIsEnabled)); + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPre8_3.h b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPre8_3.h new file mode 100644 index 0000000..fafb8c7 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPre8_3.h @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverrider.h" + +@interface SDStatusBarOverriderPre8_3 : NSObject + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPre8_3.m b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPre8_3.m new file mode 100644 index 0000000..184e2f0 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/SimulatorStatusMagic/SDStatusBarManager/SDStatusBarOverriderPre8_3.m @@ -0,0 +1,212 @@ +// -------------------------------------------------------------------------------- +// The MIT License (MIT) +// +// Copyright (c) 2014 Shiny Development +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// -------------------------------------------------------------------------------- + +#import +#import "SDStatusBarOverriderPre8_3.h" + +/* Generated by RuntimeBrowser. + Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/UIKit.framework/UIKit + */ + +typedef struct { + char boolitemIsEnabled[25]; + char timeString[64]; + int gsmSignalStrengthRaw; + int gsmSignalStrengthBars; + char serviceString[100]; + char serviceCrossfadeString[100]; + char serviceImages[2][100]; + char operatorDirectory[1024]; + unsigned int serviceContentType; + int wifiSignalStrengthRaw; + int wifiSignalStrengthBars; + unsigned int dataNetworkType; + int batteryCapacity; + unsigned int batteryState; + char batteryDetailString[150]; + int bluetoothBatteryCapacity; + int thermalColor; + unsigned int thermalSunlightMode : 1; + unsigned int slowActivity : 1; + unsigned int syncActivity : 1; + BOOL activityDisplayId[256]; + unsigned int bluetoothConnected : 1; + unsigned int displayRawGSMSignal : 1; + unsigned int displayRawWifiSignal : 1; + unsigned int locationIconType : 1; + unsigned int quietModeInactive : 1; + unsigned int tetheringConnectionCount; +} StatusBarRawData; + +typedef struct { + char booloverrideItemIsEnabled[25]; + unsigned int overrideTimeString : 1; + unsigned int overrideGsmSignalStrengthRaw : 1; + unsigned int overrideGsmSignalStrengthBars : 1; + unsigned int overrideServiceString : 1; + unsigned int overrideServiceImages : 2; + unsigned int overrideOperatorDirectory : 1; + unsigned int overrideServiceContentType : 1; + unsigned int overrideWifiSignalStrengthRaw : 1; + unsigned int overrideWifiSignalStrengthBars : 1; + unsigned int overrideDataNetworkType : 1; + unsigned int disallowsCellularDataNetworkTypes : 1; + unsigned int overrideBatteryCapacity : 1; + unsigned int overrideBatteryState : 1; + unsigned int overrideBatteryDetailString : 1; + unsigned int overrideBluetoothBatteryCapacity : 1; + unsigned int overrideThermalColor : 1; + unsigned int overrideSlowActivity : 1; + unsigned int overrideActivityDisplayId : 1; + unsigned int overrideBluetoothConnected : 1; + unsigned int overrideDisplayRawGSMSignal : 1; + unsigned int overrideDisplayRawWifiSignal : 1; + StatusBarRawData values; +} StatusBarOverrideData; + +@class UIStatusBarServerClient; + +@interface UIStatusBarServer : NSObject { + UIStatusBarServerClient *_statusBar; + struct __CFRunLoopSource { } *_source; +} + +@property(retain) UIStatusBarServerClient * statusBar; + ++ (unsigned int)_serverPort; ++ (void)runServer; ++ (id)getDoubleHeightStatusStringForStyle:(long long)arg1; ++ (bool)getGlowAnimationStateForStyle:(long long)arg1; ++ (int)getStyleOverrides; ++ (StatusBarOverrideData *)getStatusBarOverrideData; ++ (const StatusBarRawData*)getStatusBarData; ++ (void)permanentizeStatusBarOverrideData; ++ (void)postStatusBarOverrideData:(StatusBarOverrideData*)arg1; ++ (void)postStatusBarData:(const StatusBarRawData*)arg1 withActions:(int)arg2; ++ (unsigned int)_publisherPort; ++ (double)getGlowAnimationEndTimeForStyle:(long long)arg1; ++ (void)removeStatusBarItem:(int)arg1; ++ (void)addStatusBarItem:(int)arg1; ++ (void)postDoubleHeightStatusString:(id)arg1 forStyle:(long long)arg2; ++ (void)postGlowAnimationState:(bool)arg1 forStyle:(long long)arg2; ++ (void)removeStyleOverrides:(int)arg1; ++ (void)addStyleOverrides:(int)arg1; +@end + +@implementation SDStatusBarOverriderPre8_3 + +@synthesize timeString; +@synthesize dateString; +@synthesize carrierName; +@synthesize bluetoothConnected; +@synthesize bluetoothEnabled; +@synthesize batteryDetailEnabled; +@synthesize networkType; +@synthesize iPadDateEnabled; +@synthesize iPadGsmSignalEnabled; + +- (void)enableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Set 9:41 time in current localization + overrides->overrideTimeString = 1; + strcpy(overrides->values.timeString, [self.timeString cStringUsingEncoding:NSUTF8StringEncoding]); + + // Enable 5 bars of mobile (iPhone only) + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + overrides->booloverrideItemIsEnabled[3] = 1; + overrides->values.boolitemIsEnabled[3] = 1; + overrides->overrideGsmSignalStrengthBars = 1; + overrides->values.gsmSignalStrengthBars = 5; + } + + overrides->overrideDataNetworkType = self.networkType != SDStatusBarManagerNetworkTypeWiFi; + overrides->values.dataNetworkType = self.networkType - 1; + + // Remove carrier text for iPhone, set it to "iPad" for the iPad + NSString *carrierText = self.carrierName; + if ([carrierText length] <= 0) { + carrierText = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? @"" : @"iPad"; + } + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [carrierText cStringUsingEncoding:NSUTF8StringEncoding]); + + // Battery + overrides->booloverrideItemIsEnabled[8] = 1; + overrides->values.boolitemIsEnabled[8] = 1; + overrides->overrideBatteryDetailString = 1; + strcpy(overrides->values.batteryDetailString, [self.batteryDetailEnabled? @"100%" : @" " cStringUsingEncoding:NSUTF8StringEncoding]); + + // Bluetooth + overrides->booloverrideItemIsEnabled[11] = self.bluetoothEnabled; + overrides->values.boolitemIsEnabled[11] = self.bluetoothEnabled; + if (self.bluetoothEnabled) { + overrides->overrideBluetoothConnected = self.bluetoothConnected; + overrides->values.bluetoothConnected = self.bluetoothConnected; + } + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // if battery detail was not required, then it was set to one space @" ", so let's correct it here in case bluetooth icon comes after it + if (!self.batteryDetailEnabled) { + strcpy(overrides->values.batteryDetailString, [@"" cStringUsingEncoding:NSUTF8StringEncoding]); + [UIStatusBarServer postStatusBarOverrideData:overrides]; + } + + // Lock in the changes, reset simulator will remove this + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +- (void)disableOverrides +{ + StatusBarOverrideData *overrides = [UIStatusBarServer getStatusBarOverrideData]; + + // Remove specific overrides (separate flags) + overrides->overrideTimeString = 0; + overrides->overrideGsmSignalStrengthBars = 0; + overrides->overrideDataNetworkType = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBatteryDetailString = 0; + overrides->overrideBluetoothConnected = 0; + + // Remove all overrides that use the array of bools + for (int i = 0; i < 25; i++) { + overrides->booloverrideItemIsEnabled[i] = 0; + overrides->values.boolitemIsEnabled[i] = 0; + } + + // Carrier text (it's an override to set it back to the default) + overrides->overrideServiceString = 1; + strcpy(overrides->values.serviceString, [NSLocalizedString(@"Carrier", @"Carrier") cStringUsingEncoding:NSUTF8StringEncoding]); + + // Actually update the status bar + [UIStatusBarServer postStatusBarOverrideData:overrides]; + + // Have to call this to remove all the overrides + [UIStatusBarServer permanentizeStatusBarOverrideData]; +} + +@end diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/CHANGELOG.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/CHANGELOG.md new file mode 100644 index 0000000..0dd758e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/CHANGELOG.md @@ -0,0 +1,666 @@ +# Sourcery CHANGELOG + +--- +## 0.16.1 + +### Bug fixes +- Fix ReceivedInvocations's type for the method which have only one parameter in AutoMockable.stencil +- Fix missing folder error that could happen when running a Swift template with existing cache +- Don't add indentation to empty line when using inline generated code. + +### Internal Changes + +- Removed dependency on SwiftTryCatch pod in order to avoid Swift Package Manager errors. + +## 0.16.0 + +- Replaces environment variables inside .yml configurations (like ${PROJECT_NAME}), if a value is set. +- Fixes warning in generated AutoMockable methods that have implicit optional return values +- Support for `optional` methods in ObjC protocols +- Support for parsing lazy vars into Variable's attributes. +- Updated Stencil to 0.13.1 and SwiftStencilKit to 2.7.0 +- In Swift templates CLI arguments should now be accessed via `argument` instead of `arguments`, to be consistent with Stencil and JS templates. +- Now in swift templates you can define types, extensions and use other Swift features that require file scope, without using separate files. All templates code is now placed at the top level of the template executable code, instead of being placed inside an extension of `TemplateContext` type. +- Fixed missing generated code annotated with `inline` annotation when corresponding annotation in sources are missing. This generated code will be now present in `*.generated.swift` file. +- Updated AutoHashable template to use Swift 4.2's `hash(into:)` method from `Hashable`, and enable support for inheritance. +- Record all method invocations in the `AutoMockable` template. +- Replace `swiftc` with the Swift Package Manager to build Swift templates +- Swift templates can now be used when using a SPM build of Sourcery. + +## 0.15.0 + +### New Features + +- You can now pass a json string as a command line arg or annotation and have it parsed into a Dictionary or Array to be used in the template. +- Support for Xcode 10 and Swift 4.2 + +## 0.14.0 + +### New Features + +- You can now include entire Swift files in Swift templates +- You can now use AutoEquatable with annotations +- Content from multiple file annotations will now be concatenated instead of writing only the latest generated content. + +For example content generated by two following templates + +``` +// sourcery:file:Generated/Foo.swift +line one +// sourcery:end +``` +and + +``` +// sourcery:file:Generated/Foo.swift +line two +// sourcery:end +``` + +will be written to one file: + +``` +line one + +line two + +``` + +### Internal Changes + +- Use AnyObject for class-only protocols + +### Bug fixes + +- Fixed parsing associated enum cases in Xcode 10 +- Fixed AutoEquatable access level for `==` func +- Fixed path of generated files when linked to Xcode project +- Fixed extraction of inline annotations in multi line comments with documentation style +- Fixed compile error when used AutoHashable in NSObject subclass. + +## 0.13.1 + +### New Features + +- Added support for enums in AutoCodable template +- You can now specify the base path for the Sourcery cache directory with a `cacheBasePath` key in the config file + +## 0.13.0 + +### New Features + +- Added AutoCodable template + +### Bug fixes + +- Fixed parsing protocol method return type followed by declaration with attribute +- Fixed inserting auto-inlined code on the last line of declaration body +- AutoEquatable and AutoHashable templates should not add protocol conformances in extensions + +## 0.12.0 + +### Internal Changes + +- Migrate to Swift 4.1 and Xcode 9.3 + +## 0.11.2 + +### Bug fixes + +- Autocases template not respecting type access level +- Ensure SPM and CocoaPods dependencies match +- Improve AutoMockable template to handle methods with optional return values +- Fixed crash while compiling swift templates + +## 0.11.1 + +### Internal changes + +- Do not fail the build if slather fails +- Updated SourceKitten to 0.20.0 + +### Bug fixes + +- Fixed parsing protocol methods return type (#579) + +## 0.11.0 + +### New Features + +- Supports adding new templates files while in watcher mode +- Supports adding new source files while in watcher mode +- Added support for subscripts +- Added `isGeneric` property for `Method` +- You can now pass additional arguments one by one, i.e. `--args arg1=value1 --args arg2 --args arg3=value3` +- Improved support for generic types. Now you can access basic generic type information with `TypeName.generic` property +- added `@objcMembers` attribute +- Moved EJS and Swift templates to separate framework targets +- EJS templates now can be used when building Sourcery with SPM +- Added Closures to AutoMockable +- You can now link generated files to projects using config file +- You can now use AutoMockable with annotations +- Updated to latest version of Stencil (commit 9184720) +- Added support for annotation namespaces +- Added `--exclude-sources` and `--exclude-templates` CLI options + +** Breaking ** + +- @objc attribute now has a `name` argument that contains Objective-C name of attributed declaration +- Type collections `types.based`, `types.implementing` and `types.inheriting` now return non-optional array. If no types found, empty array will be returned. +This is a breaking change for template code like this: + + ```swift +<% for type in (types.implementing["SomeProtocol"] ?? []) { %> +``` + + The new correct syntax would be: + + ```swift +<% for type in types.implementing["SomeProtocol"] { %> +``` + +### Internal changes + +- Migrate to Swift 4, SwiftPM 4 and Xcode 9.2 +- `selectorName` for methods without parameters now will not contain `()` +- `returnTypeName` for initializers will be the type name of defining type, with `?` for failable initializers +- Improved compile time of AutoHashable template +- Updated StencilSwiftKit and Stencil to 0.10.1 + +### Bug fixes + +- Fixes FSEvents errors reported in #465 that happen on Sierra +- JS exceptions no more override syntax errors in JS templates +- Accessing unknown property on `types` now results in a better error than `undefined is not an object` in JS templates +- Fixed issue in AutoMockable, where generated non-optional variables wouldn't meet protocol's requirements. For this purpose, underlying variable was introduced +- Fixed `inline:auto` not inserting code if Sourcery is run with cache enabled #467 +- Fixed parsing @objc attributes on types +- Fixed parsing void return type in methods without spaces between method name and body open curly brace and in protocols +- Fixed AutoMockable template generating throwing method with void return type +- Fixed parsing throwing initializers +- Fixed trying to process files which do not exist +- Automockable will not generate mocks for methods defined in protocol extensions +- Fixed parsing typealiases of generic types +- AutoLenses template will create lenses only for stored properties +- Fixed resolving actual type name for generics with inner types +- Fixed parsing nested types from extensions +- Fixed removing back ticks in types names +- Fixed creating output folder if it does not exist +- Fixed inferring variable types with closures and improved inferring types of enum default values +- Fixed enum cases with empty parenthesis not having () associated value + +## 0.10.1 + +* When installing Sourcery via CocoaPods, the unneeded `file.zip` is not kept in `Pods/Sourcery/` anymore _(freeing ~12MB on each install of Sourcery made via CocoaPods!)_. + +## 0.10.0 + +### New Features + +- Added test for count Stencil filter +- Added new reversed Stencil filter +- Added new isEmpty Stencil filter +- Added new sorted and sortedDescending Stencil filters. This can sort arrays by calling e.g. `protocol.allVariables|sorted:"name"` +- Added new toArray Stencil filter +- Added a console warning when a yaml is available but any parameter between 'sources', templates', 'forceParse', 'output' are provided + +### Internal changes + +- Add release to Homebrew rake task +- Fixed Swiftlint warnings +- Fixed per file generation if there is long (approx. 150KB) output inside `sourcery:file` annotation +- Do not generate default.profraw +- Remove filters in favor of same filters from StencilSwiftKit + +## 0.9.0 + +### New Features + +- Added support for file paths in `config` parameter +- Added `isDeinitializer` property for methods +- Improved config file validation and error reporting +- Various improvements for `AutoMockable` template: + - support methods with reserved keywords name + - support methods that throws + - improved generated declarations names + +### Bug fixes + +- Fixed single file generation not skipping writing the file when there is no generated content + +### Internal changes + +- Updated dependencies for Swift 4 +- Update internal ruby dependencies + +## 0.8.0 + +### New Features + +- Added support in `AutoHashable` for static variables, `[Hashable]` array and `[Hashable: Hashable]` dictionary +- Added `definedInType` property for `Method` and `Variable` +- Added `extensions` filter for stencil template +- Added include support in Swift templates +- Swift templates now can throw errors. You can also throw just string literals. +- Added support for TypeName in string filters (except filters from StencilSwiftKit). + +### Bug fixes + +- Fixed linker issue when using Swift templates +- Updated `AutoMockable` to exclude generated code collisions +- Fixed parsing of default values for variables that also have a body (e.g. for `didSet`) +- Fixed line number display when an error occur while parsing a Swift template +- Fixed `rsync` issue on `SourceryRuntime.framework` when using Swift templates +- Fixed `auto:inline` for nested types (this concerns the first time the code is inserted) + +### Internal changes + +- Fix link for template in docs +- Fix running Sourcery in the example app +- Add step to update internal boilerplate code during the release + + +## 0.7.2 + +### Internal changes + +- Add Version.swift to represent CLI tool version + + +## 0.7.1 + +### Bug fixes + +- Fixed regression in parsing templates from config file +- Removed meaningless `isMutating` property for `Variable` + +### Internal changes + +- Improvements in release script +- Updated boilerplate code to reflect latest changes + + +## 0.7.0 + +### New Features + +- Added `inout` flag for `MethodParameter` +- Added parsing `mutating` and `final` attributes with convenience `isMutating` and `isFinal` properties +- Added support for `include` Stencil tag +- Added support for excluded paths + +### Bug fixes + +- Fixed inserting generated code inline automatically at wrong position +- Fixed regression in AutoEquatable & AutoHashable template with private computed variables + +### Internal changes + +- Internal release procedure improvements +- Improved `TemplatesTests` scheme running +- Fixed swiftlint warnings (version 0.19.0) + + +## 0.6.1 + +### New Features + +- Paths in config file are now relative to config file path by default, absolute paths should start with `/` +- Improved logging and error reporting, added `--quiet` CLI option, added runtime errors for using invalid types in `implementing` and `inheriting` +- Added support for includes in EJS templates (for example: `<%- include('myTemplate.js') %>`) +- Add the `lowerFirst` filter for Stencil templates. +- Added `isRequired` property for `Method` +- Improved parsing of closure types +- Check if Current Project Version match version in podspec in release task +- Improved swift templates performance +- Added `// sourcery:file` annotation for source code + +### Bug fixes + +- Fixed detecting computed properties +- Fixed typo in `isConvenienceInitialiser` property +- Fixed creating cache folder when cache is disabled +- Fixed parsing multiple enum cases annotations +- Fixed parsing inline annotations when there is an access level or attribute +- Fixed parsing `required` attribute +- Fixed typo in `guides/Writing templates.md` + +### Internal changes + +- Improved `AutoMockable.stencil` to support protocols with `init` methods +- Improved `AutoCases.stencil` to use `let` instead of computed `var` +- Updated StencilSwiftKit to 1.0.2 which includes Stencil 0.9.0 +- Adding docset to release archive +- Add tests for bundled stencil templates +- Moved to CocoaPods 1.2.1 +- Made Array.parallelMap's block non-escaping + + +## 0.6.0 + +### New Features + +- Added some convenience accessors for classic, static and instance methods, and types and contained types grouped by names + +## 0.6 + +### New Features + +- Added support for inline code generation without requiring explicit `// sourcery:inline` comments in the source files. To use, use `sourcery:inline:auto` in a template: `// sourcery:inline:auto:MyType.TemplateName` +- Added `isMutable` property for `Variable` +- Added support for scanning multiple targets +- Added access level filters and disabled filtering private declarations +- Added support for inline comments for annotations with `/*` and `*/` +- Added annotations for enum case associated values and method parameters +- Added `isConvenienceInitializer` property for `Method` +- Added `defaultValue` for variables and method parameters +- Added docs generated with jazzy +- Sourcery now will not create empty files and will remove existing generated files with empty content if CLI flag `prune` is set to `true` (`false` by default) +- Sourcery now will remove inline annotation comments from generated code. +- Added `rethrows` property to `Method` +- Allow duplicated annotations to be agregated into array +- Added ejs-style tags to control whitespaces and new lines in swift templates +- Added CLI option to provide path to config file + +### Bug Fixes + +- Inserting multiple inline code block in one file +- Suppress warnings when compiling swift templates +- Accessing protocols in Swift templates +- Crash that would happen sometimes when parsing typealiases + +### Internal changes + +- Replaced `TypeReflectionBox` and `GenerationContext` types with common `TemplateContext`. + +## 0.5.9 + +### New Features + +- Added flag to check if `TypeName` is dictionary +- Added support for multiple sources and templates paths, sources, templates and output paths now should be provided with `--sources`, `--templates` and `--output` options +- Added support for YAML file configuration +- Added generation of non-swift files using `sourcery:file` annotation + +### Bug Fixes + +- Fixed observing swift and js templates +- Fixed parsing generic array types +- Fixed using dictionary in annotations + +## 0.5.8 + +### New Features + +- Added parsing array types +- Added support for JavaScript templates (using EJS) + +### Bug Fixes + +- Fixed escaping variables with reserved names +- Fixed duplicated methods and variables in `allMethods` and `allVariables` +- Fixed trimming attributes in type names + +## 0.5.7 + +### Bug Fixes +- Cache initial file contents, including the inline generated ranges so that they are always up to date + +## 0.5.6 + +### New Features + +- Added per file code generation + +### Bug Fixes + +- Fixed parsing annotations with complex content +- Fixed inline parser using wrong caching logic + +## 0.5.5 + +### New Features + +- Sourcery will no longer write files if content didn't change, this improves behaviour of things depending on modification date like Xcode, Swiftlint. + +### Internal changes + +- Improved support for contained types + +### Bug Fixes + +- Fixes cache handling that got broken in 0.5.4 + +## 0.5.4 + +### New Features + +- Added inline code generation +- Added `isClosure` property to `TypeName` to detect closure types + +### Bug Fixes + +- Fixed parsing of associated values separater by newlines +- Fixed preserving order of inherited types +- Improved support for throwing methods in protocols +- Fixed extracting parameters of methods with closures in their bodies +- Fixed extracting method return types of tuple types +- Improved support for typealises as tuple elements types +- Method parameters with `_` argument label will now have `nil` in `argumentLabel` property +- Improved support for generic methods +- Improved support for contained types + +### Internal changes + +- adjusted internal templates and updated generated code +- moved methods parsing related tests in a separate spec + +## 0.5.3 + +### New Features +- Added support for method return types with `throws` and `rethrows` +- Added a new filter `replace`. Usage: `{{ name|replace:"substring","replacement" }}` - replaces occurrences of `substring` with `replacement` in `name` (case sensitive) +- Improved support for inferring types of variables with initial values +- Sourcery is now bundling a set of example templates, you can access them in Templates folder. +- We now use parallel parsing and cache source artifacts. This leads to massive performance improvements: +- e.g. on big codebase of over 300 swift files: +``` +Sourcery 0.5.2 +Processing time 8.69941002130508 seconds + +Sourcery 0.5.3 +First time 4.69904798269272 seconds +Subsequent time: 0.882099032402039 seconds +``` + +### Bug Fixes +- Method `accessLevel` was not exposed as string so not accessible properly via templates, fixed that. +- Fixes on Swift Templates + +## 0.5.2 + +### New Features + +- Added support for `ImplicitlyUnwrappedOptional` +- `actualTypeName` property of `Method.Parameter`, `Variable`, `Enum.Case.AssociatedValue`, `TupleType.Element` now returns `typeName` if type is not a type alias +- `Enum` now contains type information for its raw value type. `rawType` now return `Type` object, `rawTypeName` returns its `TypeName` +- Added `annotated` filter to filter by annotations +- Added negative filters counterparts +- Added support for attributes, i.e. `@escaping` +- Experimental support for Swift Templates + +- Swift Templates are now supported + +``` +<% for type in types.classes { %> + extension <%= type.name %>: Equatable {} + + <% if type.annotations["showComment"] != nil { %> // <%= type.name %> has Annotations <% } %> + + func == (lhs: <%= type.name %>, rhs: <%= type.name %>) -> Bool { + <% for variable in type.variables { %> if lhs.<%= variable.name %> != rhs.<%= variable.name %> { return false } + <% } %> + return true + } +<% } %> +``` + +### 0.5.1 + +### New Features +- Variables with default initializer are now supported, e.g. `var variable = Type(...)` +- Added support for special escaped names in enum cases e.g. `default` or `for` +- Added support for tuple types and `tuple` filter for variables +- Enum associated values now have `localName` and `externalName` properties. +- Added `actualTypeName` for `TypeName` that is typealias +- Added `implements`, `inherits` and `based` filters + +### Bug Fixes +- Using protocols doesn't expose variables using KVC, which meant some of the typeName properties weren't accessible via Templates, we fixed that using Sourcery itself to generate specific functions. +- Fixed parsing typealiases for tuples and closure types +- Fixed parsing associated values of generic types + +### Internal Changes +- Performed significant refactoring and simplified mutations in parsers + +## 0.5.0 +- You can now pass arbitrary values to templates with `--args` argument. +- Added `open` access level +- Type `inherits` and `implements` now allow you to access full type information, not just name +- Type `allVariables` will now include all variables, including those inherited from supertype and known protocols. +- Type `allMethods` will now include all methods, including those inherited from supertype and known protocols. +- AssociatedValue exposes `unwrappedTypeName`, `isOptional` +- New Available stencil filters: + - `static`, `instance`, `computed`, `stored` for Variables + - `enum`, `class`, `struct`, `protocol` for Types + - `class`, `initializer`, `static`, `instance` for Methods + - `count` for Arrays, this is used when chaining arrays with filters where Stencil wouldn't allow us to do `.count`, e.g. `{{ variables|instance|count }}` +- Now you can avoid inferring unknown protocols as enum raw types by adding conformance in extension (instead of `enum Foo: Equatable {}` do `enum Foo {}; extension Foo: Equatable {}`) + +### Internal changes +- Refactor code around typenames + +## 0.4.9 + +### New Features +- Watch mode now works with folders, reacting to source-code changes and adding templates/source files. +- When using watch mode, status info will be displayed in the generated code so that you don't need to look at console at all. +- You can now access types of enum's associated values +- You can now access type's `methods` and `initializers` + +## 0.4.8 + +### New Features +- You can now access `supertype` of a class +- Associated values will now automatically use idx as name if no name is provided + +### Bug Fixes +- Fix dealing with multibyte characters +- `types.implementing` and `types.based` should include protocols that are based on other protocols + +### Internal changes +- TDD Development is now easier thanks to Diffable results, no longer we need to scan wall of text on failures, instead we see exactly what's different. + +## 0.4.7 + +### New Features +- Added `contains`, `hasPrefix`, `hasPrefix` filters + +### Bug Fixes +- AccessLevel is now stored as string + +## 0.4.6 + +### Bug Fixes +- Typealiases parsing could cause crash, implemented a workaround for that until we can find a little more reliable solution + +## 0.4.5 + +### New Features + +* Swift Package Manager support. + +## 0.4.4 + +### New Features + +* Enum cases also have annotation support + +### Internal changes + +* Improved handling of global and local typealiases. + +## 0.4.3 + +### New Features +* Add upperFirst stencil filter + +## 0.4.2 + +### Bug Fixes + +* Fixes a bug with flattening `inherits`, `implements` for protocols implementing other protocols +* Improve `rawType` logic for Enums + +### New Features + +* Annotations can now be declared also with sections e.g. `sourcery:begin: attribute1, attribute2 = 234` +* Adds scanning class variables as static + +### Internal changes + +* Refactored models +* Improved performance of annotation scanning + +## 0.4.1 + +### New Features + +* Implements inherits, implements, based reflection on each Type +* Flattens inheritance, e.g. Foo implements Decodable, then FooSubclass also implements it + +### Internal changes + +* Stop parsing private variables as they wouldn't be accessible to code-generated code + +## 0.4.0 + +### New Features + +* improve detecting raw type +* add `isGeneric` property + +## 0.3.9 + +### New Features + +* Enables support for scanning extensions of unknown type, providing partial metadata via types.based or types.all reflection + +## 0.3.8 +### New Features + +* Adds real type reflection into Variable, not only it's name +* Resolves known typealiases + +## 0.3.7 +### Bug Fixes + +* Fixes a bug that caused Sourcery to drop previous type information when encountering generated code, closes #33 + +## 0.3.6 +### Bug Fixes + +* Fixes bug in escaping path +* Fixes missing protocol variant in kind + + +## 0.3.5 + +### New Features +* added support for type/variable source annotations +* added property kind to Type, it contains info whether this is struct, class or enum entry +* Automatically skips .swift files that were generated with Sourcery + +### Internal changes + +* improved detecting enums with rawType diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/LICENSE b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/LICENSE new file mode 100644 index 0000000..820bff4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Krzysztof Zabłocki + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/README.md b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/README.md new file mode 100644 index 0000000..44e739f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/README.md @@ -0,0 +1,181 @@ +[![CircleCI](https://circleci.com/gh/krzysztofzablocki/Sourcery.svg?style=shield)](https://circleci.com/gh/krzysztofzablocki/Sourcery) +[![codecov](https://codecov.io/gh/krzysztofzablocki/Sourcery/branch/master/graph/badge.svg)](https://codecov.io/gh/krzysztofzablocki/Sourcery) +[![docs](https://cdn.rawgit.com/krzysztofzablocki/Sourcery/master/docs/badge.svg)](https://cdn.rawgit.com/krzysztofzablocki/Sourcery/master/docs/index.html) +[![Version](https://img.shields.io/cocoapods/v/Sourcery.svg?style=flat)](http://cocoapods.org/pods/Sourcery) +[![License](https://img.shields.io/cocoapods/l/Sourcery.svg?style=flat)](http://cocoapods.org/pods/Sourcery) +[![Platform](https://img.shields.io/cocoapods/p/Sourcery.svg?style=flat)](http://cocoapods.org/pods/Sourcery) + + + +**Sourcery** is a code generator for Swift language, built on top of Apple's own SourceKit. It extends the language abstractions to allow you to generate boilerplate code automatically. + +It's used in over 30,000 projects on both iOS and macOS and it powers some of the most popular and critically-acclaimed apps you have used. Its massive community adoption was one of the factors that pushed Apple to implement derived Equality and automatic Codable conformance. Sourcery is maintained by a growing community of [contributors](https://github.com/krzysztofzablocki/Sourcery/graphs/contributors). + +Try **Sourcery** for your next project or add it to an existing one -- you'll save a lot of time and be happy you did! + +## TL;DR +Sourcery allows you to get rid of repetitive tasks. An example might be implementing `Equatable`, without Sourcery you need to implement stuff like this: + +```swift +extension Person: Equatable { + static func ==(lhs: Person, rhs: Person) -> Bool { + guard lhs.firstName == rhs.firstName else { return false } + guard lhs.lastName == rhs.lastName else { return false } + guard lhs.birthDate == rhs.birthDate else { return false } + return true + } +} +``` + +This is trivial code but imagine doing this across ten types. Across fifty. How many structs and classes are in your project? + +Sourcery removes the need to write this code. And if you refactor or add properties, the equality code will be automatically updated for you, eliminating possible human errors. + +Sourcery automation can be applied to many more domains, e.g. + +- Equality & Hashing +- Enum cases & Counts +- Lenses +- Mocks & Stubs +- LinuxMain +- Decorators +- JSON coding +- NSCoding and Codable + +It's trivial to write new templates to remove boilerplate that is specific to your projects. + +## How To Get Started +There are plenty of tutorials for different uses of Sourcery, and you can always ask for help in our [Swift Forum Category](https://forums.swift.org/c/related-projects/sourcery). + +- [The Magic of Sourcery](https://www.caseyliss.com/2017/3/31/the-magic-of-sourcery) is a great starting tutorial +- [Generating Swift Code for iOS](https://www.raywenderlich.com/158803/sourcery-tutorial-generating-swift-code-ios) deals with JSON handling code +- [How To Automate Swift Boilerplate with Sourcery](https://atomicrobot.io/blog/sourcery/) generates conversions to dictionaries +- [Codable Enums](https://littlebitesofcocoa.com/318-codable-enums) implements Codable support for Enumerations +- [Building an API client with Sourcery](https://littlebitesofcocoa.com/295-building-an-api-client-with-sourcery-key-value-annotations) builds API client leveraging Sourcery annotations +- [Metaprogramming in Swift](https://www.youtube.com/watch?v=Ukm70Ibk_bY) is a video from CocoaHeads where Krzysztof introduces Sourcery + + +## Installation + +- _Binary form_ + + Download the latest release with the prebuilt binary from [release tab](https://github.com/krzysztofzablocki/Sourcery/releases/latest). Unzip the archive into the desired destination and run `bin/sourcery` + +- _[Homebrew](https://brew.sh)_ + + `brew install sourcery` + + +- _[CocoaPods](https://cocoapods.org)_ + + Add `pod 'Sourcery'` to your `Podfile` and run `pod update Sourcery`. This will download the latest release binary and will put it in your project's CocoaPods path so you will run it with `$PODS_ROOT/Sourcery/bin/sourcery` + + +- _[Mint](https://github.com/yonaskolb/Mint)_ + + Run `mint run krzysztofzablocki/Sourcery`. + +- _Building from source_ + + Download the latest release source code from [the release tab](https://github.com/krzysztofzablocki/Sourcery/releases/latest) or clone the repository and build Sourcery manually. + + - _Building with Swift Package Manager_ + + Run `swift build -c release` in the root folder. This will create a `.build/release` folder and will put the binary there. Move the **whole `.build/release` folder** to your desired destination and run with `path_to_release_folder/sourcery` + + > Note: JS templates are not supported when building with SPM yet. + + - _Building with Xcode_ + + Open `Sourcery.xcworkspace` and build with `Sourcery-Release` scheme. This will create `Sourcery.app` in the Derived Data folder. You can copy it to your desired destination and run with `path_to_sourcery_app/Sourcery.app/Contents/MacOS/Sourcery` + +## Documentation + +Full documentation for the latest release is available [here](https://cdn.rawgit.com/krzysztofzablocki/Sourcery/master/docs/index.html). + +## Usage + +Sourcery is a command line tool; you can either run it manually or in a custom build phase using the following command: + +``` +$ ./sourcery --sources --templates --output +``` + +> Note: this command differs depending on how you installed Sourcery (see [Installing](#installing)) + +### Command line options + +- `--sources` - Path to a source swift files or directories. You can provide multiple paths using multiple `--sources` option. +- `--templates` - Path to templates. File or Directory. You can provide multiple paths using multiple `--templates` options. +- `--force-parse` - File extensions of Sourcery generated file you want to parse. You can provide multiple extension using multiple `--force-parse` options. (i.e. `file.toparse.swift` will be parsed even if generated by Sourcery if `--force-parse toparse`). Useful when trying to implement a multiple phases generation. +- `--output` [default: current path] - Path to output. File or Directory. +- `--config` [default: current path] - Path to config file. File or Directory. See [Configuration file](#configuration-file). +- `--args` - Additional arguments to pass to templates. Each argument can have an explicit value or will have implicit `true` value. Arguments should be separated with `,` without spaces (i.e. `--args arg1=value,arg2`). Arguments are accessible in templates via `argument.name` +- `--watch` [default: false] - Watch both code and template folders for changes and regenerate automatically. +- `--verbose` [default: false] - Turn on verbose logging +- `--quiet` [default: false] - Turn off any logging, only emit errors +- `--disableCache` [default: false] - Turn off caching of parsed data +- `--prune` [default: false] - Prune empty generated files +- `--version` - Display the current version of Sourcery +- `--help` - Display help information + +### Configuration file + +Instead of CLI arguments you can use a `.sourcery.yml` configuration file: + +```yaml +sources: + - + - +templates: + - + - +force-parse: + - + - +output: + +args: + : +``` + +Read more about this configuration file [here](https://cdn.rawgit.com/krzysztofzablocki/Sourcery/master/docs/usage.html#configuration-file). + +## Contributing + +Contributions to Sourcery are welcomed and encouraged! + +It is easy to get involved. Please see the [Contributing guide](CONTRIBUTING.md) for more details. + +[A list of contributors is available through GitHub](https://github.com/krzysztofzablocki/Sourcery/graphs/contributors). + +To clarify what is expected of our community, Sourcery has adopted the code of conduct defined by the Contributor Covenant. This document is used across many open source communities, and articulates my values well. For more, see the [Code of Conduct](CODE_OF_CONDUCT.md). + +## License + +Sourcery is available under the MIT license. See [LICENSE](LICENSE) for more information. + +## Attributions + +This tool is powered by + +- [SourceKitten](https://github.com/jpsim/SourceKitten) by [JP Simard](https://github.com/jpsim) +- [Stencil](https://github.com/kylef/Stencil) and few other libs by [Kyle Fuller](https://github.com/kylef) + +Thank you! to: + +- [Mariusz Ostrowski](http://twitter.com/faktory) for creating the logo. +- [Artsy Eidolon](https://github.com/artsy/eidolon) team, because we use their codebase as a stub data for performance testing the parser. +- [Olivier Halligon](https://github.com/AliSoftware) for showing me his setup scripts for CLI tools which are powering our rakefile. + +## Other Libraries / Tools + +If you want to generate code for asset related data like .xib, .storyboards etc. use [SwiftGen](https://github.com/AliSoftware/SwiftGen). SwiftGen and Sourcery are complementary tools. + +Make sure to check my other libraries and tools, especially: +- [KZPlayground](https://github.com/krzysztofzablocki/KZPlayground) - Powerful playgrounds for Swift and Objective-C +- [KZFileWatchers](https://github.com/krzysztofzablocki/KZFileWatchers) - Daemon for observing local and remote file changes, used for building other developer tools (Sourcery uses it) + +You can [follow me on Twitter][1] for news/updates about other projects I am creating. + + [1]: http://twitter.com/merowing_ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Resources/daemon.gif b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Resources/daemon.gif new file mode 100644 index 0000000..9e16e58 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Resources/daemon.gif differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Resources/icon-128.png b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Resources/icon-128.png new file mode 100644 index 0000000..481c339 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Resources/icon-128.png differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Info.plist b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Info.plist new file mode 100644 index 0000000..efe9a09 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleIdentifier + com.jazzy.sourcery + CFBundleName + Sourcery + DocSetPlatformFamily + sourcery + isDashDocset + + dashIndexFilePath + index.html + isJavaScriptEnabled + + DashDocSetFamily + dashtoc + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/ArrayType.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/ArrayType.html new file mode 100644 index 0000000..c673e36 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/ArrayType.html @@ -0,0 +1,270 @@ + + + + ArrayType Class Reference + + + + + + + + +
+ +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

ArrayType

+
+
+
@objcMembers public final class ArrayType: NSObject, SourceryModel
+ +
+
+

Describes array type

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Type name used in declaration

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + elementTypeName + +
    +
    +
    +
    +
    +
    +

    Array element type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let elementTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + elementType + +
    +
    +
    +
    +
    +
    +

    Array element type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var elementType: Type?
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/AssociatedValue.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/AssociatedValue.html new file mode 100644 index 0000000..258214f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/AssociatedValue.html @@ -0,0 +1,326 @@ + + + + AssociatedValue Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

AssociatedValue

+
+
+
@objcMembers public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated
+ +
+
+

Defines enum case associated value

+ +
+
+
+
    +
  • +
    + + + + localName + +
    +
    +
    +
    +
    +
    +

    Associated value local name. +This is a name to be used to construct enum case value

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let localName: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + externalName + +
    +
    +
    +
    +
    +
    +

    Associated value external name. +This is a name to be used to access value in value-bindig

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let externalName: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeName + +
    +
    +
    +
    +
    +
    +

    Associated value type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let typeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + type + +
    +
    +
    +
    +
    +
    +

    Associated value type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var type: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    Annotations, that were created with // sourcery: annotation1, other = annotation value, alterantive = 2

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var annotations: [String: NSObject] = [:]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Attribute.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Attribute.html new file mode 100644 index 0000000..d56ab54 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Attribute.html @@ -0,0 +1,270 @@ + + + + Attribute Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Attribute

+
+
+
@objcMembers public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport
+ +
+
+

Describes Swift attribute

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Attribute name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + arguments + +
    +
    +
    +
    +
    +
    +

    Attribute arguments

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let arguments: [String: NSObject]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + description + +
    +
    +
    +
    +
    +
    +

    Attribute description that can be used in a template.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var description: String
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Class.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Class.html new file mode 100644 index 0000000..77f69f5 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Class.html @@ -0,0 +1,243 @@ + + + + Class Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Class

+
+
+
@objc(SwiftClass) @objcMembers public final class Class: Type
+ +
+
+

Descibes Swift class

+ +
+
+
+
    +
  • +
    + + + + kind + +
    +
    +
    +
    +
    +
    +

    Returns class

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var kind: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isFinal + +
    +
    +
    +
    +
    +
    +

    Whether type is final

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isFinal: Bool
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/ClosureType.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/ClosureType.html new file mode 100644 index 0000000..1f046ba --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/ClosureType.html @@ -0,0 +1,432 @@ + + + + ClosureType Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

ClosureType

+
+
+
@objcMembers public final class ClosureType: NSObject, SourceryModel
+ +
+
+

Describes closure type

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Type name used in declaration with stripped whitespaces and new lines

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + parameters + +
    +
    +
    +
    +
    +
    +

    List of closure parameters

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let parameters: [MethodParameter]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + returnTypeName + +
    +
    +
    +
    +
    +
    +

    Return value type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let returnTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + actualReturnTypeName + +
    +
    +
    +
    +
    +
    +

    Actual return value type name if declaration uses typealias, otherwise just a returnTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualReturnTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + returnType + +
    +
    +
    +
    +
    +
    +

    Actual return value type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var returnType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isOptionalReturnType + +
    +
    +
    +
    +
    +
    +

    Whether return value type is optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isOptionalReturnType: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Whether return value type is implicitly unwrapped optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isImplicitlyUnwrappedOptionalReturnType: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Return value type name without attributes and optional type information

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var unwrappedReturnTypeName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + throws + +
    +
    +
    +
    +
    +
    +

    Whether closure throws

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let `throws`: Bool
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/DictionaryType.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/DictionaryType.html new file mode 100644 index 0000000..1dd606d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/DictionaryType.html @@ -0,0 +1,324 @@ + + + + DictionaryType Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

DictionaryType

+
+
+
@objcMembers public final class DictionaryType: NSObject, SourceryModel
+ +
+
+

Describes dictionary type

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Type name used in declaration

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + valueTypeName + +
    +
    +
    +
    +
    +
    +

    Dictionary value type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let valueTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + valueType + +
    +
    +
    +
    +
    +
    +

    Dictionary value type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var valueType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + keyTypeName + +
    +
    +
    +
    +
    +
    +

    Dictionary key type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let keyTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + keyType + +
    +
    +
    +
    +
    +
    +

    Dictionary key type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var keyType: Type?
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Enum.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Enum.html new file mode 100644 index 0000000..6b73aa3 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Enum.html @@ -0,0 +1,351 @@ + + + + Enum Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Enum

+
+
+
@objcMembers public final class Enum: Type
+ +
+
+

Defines Swift enum

+ +
+
+
+
    +
  • +
    + + + + kind + +
    +
    +
    +
    +
    +
    +

    Returns enum

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var kind: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + cases + +
    +
    +
    +
    +
    +
    +

    Enum cases

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var cases: [EnumCase]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + rawTypeName + +
    +
    +
    +
    +
    +
    +

    Enum raw value type name, if any

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var rawTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + rawType + +
    +
    +
    +
    +
    +
    +

    Enum raw value type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var rawType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + based + +
    +
    +
    +
    +
    +
    +

    Names of types or protocols this type inherits from, including unknown (not scanned) types

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var based: [String: String]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + hasAssociatedValues + +
    +
    +
    +
    +
    +
    +

    Whether enum contains any associated values

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var hasAssociatedValues: Bool
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/EnumCase.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/EnumCase.html new file mode 100644 index 0000000..1a98007 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/EnumCase.html @@ -0,0 +1,324 @@ + + + + EnumCase Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

EnumCase

+
+
+
@objcMembers public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated
+ +
+
+

Defines enum case

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Enum case name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + rawValue + +
    +
    +
    +
    +
    +
    +

    Enum case raw value, if any

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let rawValue: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + associatedValues + +
    +
    +
    +
    +
    +
    +

    Enum case associated values

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let associatedValues: [AssociatedValue]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    Enum case annotations

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var annotations: [String: NSObject] = [:]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + hasAssociatedValue + +
    +
    +
    +
    +
    +
    +

    Whether enum case has associated value

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var hasAssociatedValue: Bool
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/GenericType.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/GenericType.html new file mode 100644 index 0000000..02cee8c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/GenericType.html @@ -0,0 +1,243 @@ + + + + GenericType Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

GenericType

+
+
+
@objcMembers public final class GenericType: NSObject, SourceryModel
+ +
+
+

Descibes Swift generic type

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    The name of the base type, i.e. Array for Array<Int>

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeParameters + +
    +
    +
    +
    +
    +
    +

    This generic type parameters

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let typeParameters: [GenericTypeParameter]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/GenericTypeParameter.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/GenericTypeParameter.html new file mode 100644 index 0000000..2913a3e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/GenericTypeParameter.html @@ -0,0 +1,243 @@ + + + + GenericTypeParameter Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

GenericTypeParameter

+
+
+
@objcMembers public final class GenericTypeParameter: NSObject, SourceryModel
+ +
+
+

Descibes Swift generic type parameter

+ +
+
+
+
    +
  • +
    + + + + typeName + +
    +
    +
    +
    +
    +
    +

    Generic parameter type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let typeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + type + +
    +
    +
    +
    +
    +
    +

    Generic parameter type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var type: Type?
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Method.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Method.html new file mode 100644 index 0000000..318a15c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Method.html @@ -0,0 +1,1001 @@ + + + + Method Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Method

+
+
+
@objc(SwiftMethod) @objcMembers public final class Method: NSObject, SourceryModel, Annotated, Definition
+ +
+
+

Describes method

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Full method name, including generic constraints, i.e. foo<T>(bar: T)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + selectorName + +
    +
    +
    +
    +
    +
    +

    Method name including arguments names, i.e. foo(bar:)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var selectorName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + shortName + +
    +
    +
    +
    +
    +
    +

    Method name without arguments names and parenthesis, i.e. foo<T>

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var shortName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + callName + +
    +
    +
    +
    +
    +
    +

    Method name without arguments names, parenthesis and generic types, i.e. foo (can be used to generate code for method call)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var callName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + parameters + +
    +
    +
    +
    +
    +
    +

    Method parameters

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var parameters: [MethodParameter]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + returnTypeName + +
    +
    +
    +
    +
    +
    +

    Return value type name used in declaration, including generic constraints, i.e. where T: Equatable

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var returnTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + actualReturnTypeName + +
    +
    +
    +
    +
    +
    +

    Actual return value type name if declaration uses typealias, otherwise just a returnTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualReturnTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + returnType + +
    +
    +
    +
    +
    +
    +

    Actual return value type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var returnType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isOptionalReturnType + +
    +
    +
    +
    +
    +
    +

    Whether return value type is optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isOptionalReturnType: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Whether return value type is implicitly unwrapped optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isImplicitlyUnwrappedOptionalReturnType: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Return value type name without attributes and optional type information

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var unwrappedReturnTypeName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + throws + +
    +
    +
    +
    +
    +
    +

    Whether method throws

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let `throws`: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + rethrows + +
    +
    +
    +
    +
    +
    +

    Whether method rethrows

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let `rethrows`: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + accessLevel + +
    +
    +
    +
    +
    +
    +

    Method access level, i.e. internal, private, fileprivate, public, open

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let accessLevel: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isStatic + +
    +
    +
    +
    +
    +
    +

    Whether method is a static method

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isStatic: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isClass + +
    +
    +
    +
    +
    +
    +

    Whether method is a class method

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isClass: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isInitializer + +
    +
    +
    +
    +
    +
    +

    Whether method is an initializer

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isInitializer: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isDeinitializer + +
    +
    +
    +
    +
    +
    +

    Whether method is an deinitializer

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isDeinitializer: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isFailableInitializer + +
    +
    +
    +
    +
    +
    +

    Whether method is a failable initializer

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isFailableInitializer: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Whether method is a convenience initializer

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isConvenienceInitializer: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isRequired + +
    +
    +
    +
    +
    +
    +

    Whether method is required

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isRequired: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isFinal + +
    +
    +
    +
    +
    +
    +

    Whether method is final

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isFinal: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isMutating + +
    +
    +
    +
    +
    +
    +

    Whether method is mutating

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isMutating: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isGeneric + +
    +
    +
    +
    +
    +
    +

    Whether method is generic

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isGeneric: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isOptional + +
    +
    +
    +
    +
    +
    +

    Whether method is optional (in an Objective-C protocol)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isOptional: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    Annotations, that were created with // sourcery: annotation1, other = annotation value, alterantive = 2

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let annotations: [String: NSObject]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInTypeName + +
    +
    +
    +
    +
    +
    +

    Reference to type name where the method is defined, +nil if defined outside of any enum, struct, class etc

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let definedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a definedInTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualDefinedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInType + +
    +
    +
    +
    +
    +
    +

    Reference to actual type where the object is defined, +nil if defined outside of any enum, struct, class etc or type is unknown

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var definedInType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + attributes + +
    +
    +
    +
    +
    +
    +

    Method attributes, i.e. @discardableResult

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let attributes: [String: Attribute]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/MethodParameter.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/MethodParameter.html new file mode 100644 index 0000000..853133e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/MethodParameter.html @@ -0,0 +1,405 @@ + + + + MethodParameter Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

MethodParameter

+
+
+
@objcMembers public final class MethodParameter: NSObject, SourceryModel, Typed, Annotated
+ +
+
+

Describes method parameter

+ +
+
+
+
    +
  • +
    + + + + argumentLabel + +
    +
    +
    +
    +
    +
    +

    Parameter external name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var argumentLabel: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Parameter internal name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeName + +
    +
    +
    +
    +
    +
    +

    Parameter type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let typeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + inout + +
    +
    +
    +
    +
    +
    +

    Parameter flag whether it’s inout or not

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let `inout`: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + type + +
    +
    +
    +
    +
    +
    +

    Parameter type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var type: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeAttributes + +
    +
    +
    +
    +
    +
    +

    Parameter type attributes, i.e. @escaping

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var typeAttributes: [String: Attribute]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + defaultValue + +
    +
    +
    +
    +
    +
    +

    Method parameter default value expression

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var defaultValue: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    Annotations, that were created with // sourcery: annotation1, other = annotation value, alterantive = 2

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var annotations: [String: NSObject] = [:]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Protocol.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Protocol.html new file mode 100644 index 0000000..2da8c26 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Protocol.html @@ -0,0 +1,216 @@ + + + + Protocol Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Protocol

+
+
+
@objcMembers public final class Protocol: Type
+ +
+
+

Describes Swift protocol

+ +
+
+
+
    +
  • +
    + + + + kind + +
    +
    +
    +
    +
    +
    +

    Returns protocol

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var kind: String
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Struct.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Struct.html new file mode 100644 index 0000000..8323e1d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Struct.html @@ -0,0 +1,216 @@ + + + + Struct Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Struct

+
+
+
@objcMembers public final class Struct: Type
+ +
+
+

Describes Swift struct

+ +
+
+
+
    +
  • +
    + + + + kind + +
    +
    +
    +
    +
    +
    +

    Returns struct

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var kind: String
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Subscript.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Subscript.html new file mode 100644 index 0000000..8bcd50d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Subscript.html @@ -0,0 +1,624 @@ + + + + Subscript Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Subscript

+
+
+
@objcMembers public final class Subscript: NSObject, SourceryModel, Annotated, Definition
+ +
+
+

Describes subscript

+ +
+
+
+
    +
  • +
    + + + + parameters + +
    +
    +
    +
    +
    +
    +

    Method parameters

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var parameters: [MethodParameter]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + returnTypeName + +
    +
    +
    +
    +
    +
    +

    Return value type name used in declaration, including generic constraints, i.e. where T: Equatable

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var returnTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + actualReturnTypeName + +
    +
    +
    +
    +
    +
    +

    Actual return value type name if declaration uses typealias, otherwise just a returnTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualReturnTypeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + returnType + +
    +
    +
    +
    +
    +
    +

    Actual return value type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var returnType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isOptionalReturnType + +
    +
    +
    +
    +
    +
    +

    Whether return value type is optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isOptionalReturnType: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Whether return value type is implicitly unwrapped optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isImplicitlyUnwrappedOptionalReturnType: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Return value type name without attributes and optional type information

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var unwrappedReturnTypeName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isFinal + +
    +
    +
    +
    +
    +
    +

    Whether method is final

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isFinal: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + readAccess + +
    +
    +
    +
    +
    +
    +

    Variable read access level, i.e. internal, private, fileprivate, public, open

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let readAccess: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + writeAccess + +
    +
    +
    +
    +
    +
    +

    Variable write access, i.e. internal, private, fileprivate, public, open. +For immutable variables this value is empty string

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var writeAccess: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isMutable + +
    +
    +
    +
    +
    +
    +

    Whether variable is mutable or not

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isMutable: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    Annotations, that were created with // sourcery: annotation1, other = annotation value, alterantive = 2

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let annotations: [String: NSObject]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInTypeName + +
    +
    +
    +
    +
    +
    +

    Reference to type name where the method is defined, +nil if defined outside of any enum, struct, class etc

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let definedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a definedInTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualDefinedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInType + +
    +
    +
    +
    +
    +
    +

    Reference to actual type where the object is defined, +nil if defined outside of any enum, struct, class etc or type is unknown

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var definedInType: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + attributes + +
    +
    +
    +
    +
    +
    +

    Method attributes, i.e. @discardableResult

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let attributes: [String: Attribute]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TupleElement.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TupleElement.html new file mode 100644 index 0000000..3a08e08 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TupleElement.html @@ -0,0 +1,270 @@ + + + + TupleElement Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

TupleElement

+
+
+
@objcMembers public final class TupleElement: NSObject, SourceryModel, Typed
+ +
+
+

Describes tuple type element

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Tuple element name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeName + +
    +
    +
    +
    +
    +
    +

    Tuple element type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let typeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + type + +
    +
    +
    +
    +
    +
    +

    Tuple element type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var type: Type?
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TupleType.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TupleType.html new file mode 100644 index 0000000..965e350 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TupleType.html @@ -0,0 +1,243 @@ + + + + TupleType Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

TupleType

+
+
+
@objcMembers public final class TupleType: NSObject, SourceryModel
+ +
+
+

Describes tuple type

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Type name used in declaration

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + elements + +
    +
    +
    +
    +
    +
    +

    Tuple elements

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let elements: [TupleElement]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Type.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Type.html new file mode 100644 index 0000000..4c6d723 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Type.html @@ -0,0 +1,1059 @@ + + + + Type Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Type

+
+
+
@objcMembers public class Type: NSObject, SourceryModel, Annotated
+ +
+
+

Defines Swift type

+ +
+
+
+
    +
  • +
    + + + + isExtension + +
    +
    +
    +
    +
    +
    +

    Whether declaration is an extension of some type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isExtension: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + kind + +
    +
    +
    +
    +
    +
    +

    Kind of type declaration, i.e. enum, struct, class, protocol or extension

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var kind: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + accessLevel + +
    +
    +
    +
    +
    +
    +

    Type access level, i.e. internal, private, fileprivate, public, open

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let accessLevel: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Type name in global scope. For inner types includes the name of its containing type, i.e. Type.Inner

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isGeneric + +
    +
    +
    +
    +
    +
    +

    Whether type is generic

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isGeneric: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + localName + +
    +
    +
    +
    +
    +
    +

    Type name in its own scope.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var localName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + variables + +
    +
    +
    +
    +
    +
    +

    Variables defined in this type only, inluding variables defined in its extensions, +but not including variables inherited from superclasses (for classes only) and protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var variables: [Variable]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + allVariables + +
    +
    +
    +
    +
    +
    +

    All variables defined for this type, including variables defined in extensions, +in superclasses (for classes only) and protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var allVariables: [Variable]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + methods + +
    +
    +
    +
    +
    +
    +

    Methods defined in this type only, inluding methods defined in its extensions, +but not including methods inherited from superclasses (for classes only) and protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var methods: [Method]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + allMethods + +
    +
    +
    +
    +
    +
    +

    All methods defined for this type, including methods defined in extensions, +in superclasses (for classes only) and protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var allMethods: [Method]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + subscripts + +
    +
    +
    +
    +
    +
    +

    Subscripts defined in this type only, inluding subscripts defined in its extensions, +but not including subscripts inherited from superclasses (for classes only) and protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var subscripts: [Subscript]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + allSubscripts + +
    +
    +
    +
    +
    +
    +

    All subscripts defined for this type, including subscripts defined in extensions, +in superclasses (for classes only) and protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var allSubscripts: [Subscript]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + bodyBytesRange + +
    +
    +
    +
    +
    +
    +

    Bytes position of the body of this type in its declaration file if available.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var bodyBytesRange: BytesRange?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + initializers + +
    +
    +
    +
    +
    +
    +

    All initializers defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var initializers: [Method]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    All annotations for this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var annotations: [String: NSObject] = [:]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + staticVariables + +
    +
    +
    +
    +
    +
    +

    Static variables defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var staticVariables: [Variable]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + staticMethods + +
    +
    +
    +
    +
    +
    +

    Static methods defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var staticMethods: [Method]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + classMethods + +
    +
    +
    +
    +
    +
    +

    Class methods defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var classMethods: [Method]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + instanceVariables + +
    +
    +
    +
    +
    +
    +

    Instance variables defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var instanceVariables: [Variable]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + instanceMethods + +
    +
    +
    +
    +
    +
    +

    Instance methods defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var instanceMethods: [Method]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + computedVariables + +
    +
    +
    +
    +
    +
    +

    Computed instance variables defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var computedVariables: [Variable]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + storedVariables + +
    +
    +
    +
    +
    +
    +

    Stored instance variables defined in this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var storedVariables: [Variable]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + inheritedTypes + +
    +
    +
    +
    +
    +
    +

    Names of types this type inherits from (for classes only) and protocols it implements, in order of definition

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var inheritedTypes: [String]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + based + +
    +
    +
    +
    +
    +
    +

    Names of types or protocols this type inherits from, including unknown (not scanned) types

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var based = [String: String]()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + inherits + +
    +
    +
    +
    +
    +
    +

    Types this type inherits from (only for classes)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var inherits = [String: Type]()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + implements + +
    +
    +
    +
    +
    +
    +

    Protocols this type implements

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var implements = [String: Type]()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + containedTypes + +
    +
    +
    +
    +
    +
    +

    Contained types

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var containedTypes: [Type]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + containedType + +
    +
    +
    +
    +
    +
    +

    Contained types groupd by their names

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var containedType: [String: Type] = [:]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + parentName + +
    +
    +
    +
    +
    +
    +

    Name of parent type (for contained types only)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var parentName: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + parent + +
    +
    +
    +
    +
    +
    +

    Parent type, if known (for contained types only)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var parent: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + supertype + +
    +
    +
    +
    +
    +
    +

    Superclass type, if known (only for classes)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var supertype: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + attributes + +
    +
    +
    +
    +
    +
    +

    Type attributes, i.e. @objc

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var attributes: [String: Attribute]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TypeName.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TypeName.html new file mode 100644 index 0000000..1312fb8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/TypeName.html @@ -0,0 +1,675 @@ + + + + TypeName Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

TypeName

+
+
+
@objcMembers public final class TypeName: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, LosslessStringConvertible
+ +
+
+

Describes name of the type used in typed declaration (variable, method parameter or return value etc.)

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Type name used in declaration

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + generic + +
    +
    +
    +
    +
    +
    +

    The generics of this TypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var generic: GenericType?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isGeneric + +
    +
    +
    +
    +
    +
    +

    Whether this TypeName is generic

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isGeneric: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + actualTypeName + +
    +
    +
    +
    +
    +
    +

    Actual type name if given type name is a typealias

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + attributes + +
    +
    +
    +
    +
    +
    +

    Type name attributes, i.e. @escaping

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let attributes: [String: Attribute]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isOptional + +
    +
    +
    +
    +
    +
    +

    Whether type is optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isOptional: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Whether type is implicitly unwrapped optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isImplicitlyUnwrappedOptional: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + unwrappedTypeName + +
    +
    +
    +
    +
    +
    +

    Type name without attributes and optional type information

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let unwrappedTypeName: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isVoid + +
    +
    +
    +
    +
    +
    +

    Whether type is void (Void or ())

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isVoid: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isTuple + +
    +
    +
    +
    +
    +
    +

    Whether type is a tuple

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isTuple: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + tuple + +
    +
    +
    +
    +
    +
    +

    Tuple type data

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var tuple: TupleType?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isArray + +
    +
    +
    +
    +
    +
    +

    Whether type is an array

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isArray: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + array + +
    +
    +
    +
    +
    +
    +

    Array type data

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var array: ArrayType?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isDictionary + +
    +
    +
    +
    +
    +
    +

    Whether type is a dictionary

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isDictionary: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + dictionary + +
    +
    +
    +
    +
    +
    +

    Dictionary type data

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var dictionary: DictionaryType?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isClosure + +
    +
    +
    +
    +
    +
    +

    Whether type is a closure

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isClosure: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + closure + +
    +
    +
    +
    +
    +
    +

    Closure type data

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var closure: ClosureType?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + description + +
    +
    +
    +
    +
    +
    +

    Returns value of name property.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public override var description: String
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Types.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Types.html new file mode 100644 index 0000000..57866f2 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Types.html @@ -0,0 +1,435 @@ + + + + Types Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Types

+
+
+
@objcMembers public final class Types: NSObject, SourceryModel
+ +
+
+

Collection of scanned types for accessing in templates

+ +
+
+
+
    +
  • +
    + + + + all + +
    +
    +
    +
    +
    +
    +

    All known types, excluding protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var all: [Type] =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + protocols + +
    +
    +
    +
    +
    +
    +

    All known protocols

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var protocols: [Protocol] =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + classes + +
    +
    +
    +
    +
    +
    +

    All known classes

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var classes: [Class] =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + structs + +
    +
    +
    +
    +
    +
    +

    All known structs

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var structs: [Struct] =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + enums + +
    +
    +
    +
    +
    +
    +

    All known enums

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var enums: [Enum] =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + extensions + +
    +
    +
    +
    +
    +
    +

    All known extensions

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var extensions: [Type] =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + based + +
    +
    +
    +
    +
    +
    +

    Types based on any other type, grouped by its name, even if they are not known. +types.based.MyType returns list of types based on MyType

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var based: TypesCollection =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + inheriting + +
    +
    +
    +
    +
    +
    +

    Classes inheriting from any known class, grouped by its name. +types.inheriting.MyClass returns list of types inheriting from MyClass

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var inheriting: TypesCollection =
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + implementing + +
    +
    +
    +
    +
    +
    +

    Types implementing known protocol, grouped by its name. +types.implementing.MyProtocol returns list of types implementing MyProtocol

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public lazy internal(set) var implementing: TypesCollection =
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Variable.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Variable.html new file mode 100644 index 0000000..7f0172e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Classes/Variable.html @@ -0,0 +1,625 @@ + + + + Variable Class Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Variable

+
+
+
@objcMembers public final class Variable: NSObject, SourceryModel, Typed, Annotated, Definition
+ +
+
+

Defines variable

+ +
+
+
+
    +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Variable name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let name: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeName + +
    +
    +
    +
    +
    +
    +

    Variable type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let typeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + type + +
    +
    +
    +
    +
    +
    +

    Variable type, if known, i.e. if the type is declared in the scanned sources. +For explanation, see https://cdn.rawgit.com/krzysztofzablocki/Sourcery/master/docs/writing-templates.html#what-are-em-known-em-and-em-unknown-em-types

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var type: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isComputed + +
    +
    +
    +
    +
    +
    +

    Whether variable is computed and not stored

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isComputed: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isStatic + +
    +
    +
    +
    +
    +
    +

    Whether variable is static

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let isStatic: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + readAccess + +
    +
    +
    +
    +
    +
    +

    Variable read access level, i.e. internal, private, fileprivate, public, open

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let readAccess: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + writeAccess + +
    +
    +
    +
    +
    +
    +

    Variable write access, i.e. internal, private, fileprivate, public, open. +For immutable variables this value is empty string

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let writeAccess: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isMutable + +
    +
    +
    +
    +
    +
    +

    Whether variable is mutable or not

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isMutable: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + defaultValue + +
    +
    +
    +
    +
    +
    +

    Variable default value expression

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var defaultValue: String?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    Annotations, that were created with // sourcery: annotation1, other = annotation value, alterantive = 2

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var annotations: [String: NSObject] = [:]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + attributes + +
    +
    +
    +
    +
    +
    +

    Variable attributes, i.e. @IBOutlet, @IBInspectable

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var attributes: [String: Attribute]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isFinal + +
    +
    +
    +
    +
    +
    +

    Whether variable is final or not

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isFinal: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isLazy + +
    +
    +
    +
    +
    +
    +

    Whether variable is lazy or not

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isLazy: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInTypeName + +
    +
    +
    +
    +
    +
    +

    Reference to type name where the variable is defined, +nil if defined outside of any enum, struct, class etc

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let definedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a definedInTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var actualDefinedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInType + +
    +
    +
    +
    +
    +
    +

    Reference to actual type where the object is defined, +nil if defined outside of any enum, struct, class etc or type is unknown

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var definedInType: Type?
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Examples.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Examples.html new file mode 100644 index 0000000..d9b2b6c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Examples.html @@ -0,0 +1,177 @@ + + + + Examples Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Examples

+ +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Guides.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Guides.html new file mode 100644 index 0000000..94c12cd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Guides.html @@ -0,0 +1,177 @@ + + + + Guides Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Guides

+ +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Other Guides.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Other Guides.html new file mode 100644 index 0000000..df01b00 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Other Guides.html @@ -0,0 +1,183 @@ + + + + Other Guides Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Other Guides

+

The following guides are available globally.

+ +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Other Protocols.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Other Protocols.html new file mode 100644 index 0000000..afc1dab --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Other Protocols.html @@ -0,0 +1,274 @@ + + + + Other Protocols Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Other Protocols

+

The following protocols are available globally.

+ +
+
+
+
    +
  • +
    + + + + Annotated + +
    +
    +
    +
    +
    +
    +

    Describes annotated declaration, i.e. type, method, variable, enum case

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Annotated
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Definition + +
    +
    +
    +
    +
    +
    +

    Describes that the object is defined in a context of some Type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Definition: AnyObject
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Typed + +
    +
    +
    +
    +
    +
    +

    Descibes typed declaration, i.e. variable, method parameter, tuple element, enum case associated value

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Typed
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Annotated.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Annotated.html new file mode 100644 index 0000000..7770204 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Annotated.html @@ -0,0 +1,229 @@ + + + + Annotated Protocol Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Annotated

+
+
+
public protocol Annotated
+ +
+
+

Describes annotated declaration, i.e. type, method, variable, enum case

+ +
+
+
+
    +
  • +
    + + + + annotations + +
    +
    +
    +
    +
    +
    +

    All annotations of declaration stored by their name. Value can be bool, String, float NSNumber +or array of those types if you use several annotations with the same name.

    + +

    Example:

    +
    //sourcery: booleanAnnotation
    +//sourcery: stringAnnotation = "value"
    +//sourcery: numericAnnotation = 0.5
    +
    +[
    + "booleanAnnotation": true,
    + "stringAnnotation": "value",
    + "numericAnnotation": 0.5
    +]
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var annotations: [String: NSObject]
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Definition.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Definition.html new file mode 100644 index 0000000..f866e6e --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Definition.html @@ -0,0 +1,272 @@ + + + + Definition Protocol Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Definition

+
+
+
public protocol Definition: AnyObject
+ +
+
+

Describes that the object is defined in a context of some Type

+ +
+
+
+
    +
  • +
    + + + + definedInTypeName + +
    +
    +
    +
    +
    +
    +

    Reference to type name where the object is defined, +nil if defined outside of any enum, struct, class etc

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var definedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + definedInType + +
    +
    +
    +
    +
    +
    +

    Reference to actual type where the object is defined, +nil if defined outside of any enum, struct, class etc or type is unknown

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var definedInType: Type?
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a definedInTypeName

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var actualDefinedInTypeName: TypeName?
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Typed.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Typed.html new file mode 100644 index 0000000..1657432 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Protocols/Typed.html @@ -0,0 +1,324 @@ + + + + Typed Protocol Reference + + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Typed

+
+
+
public protocol Typed
+ +
+
+

Descibes typed declaration, i.e. variable, method parameter, tuple element, enum case associated value

+ +
+
+
+
    +
  • +
    + + + + type + +
    +
    +
    +
    +
    +
    +

    Type, if known

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var type: Type?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + typeName + +
    +
    +
    +
    +
    +
    +

    Type name

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var typeName: TypeName
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isOptional + +
    +
    +
    +
    +
    +
    +

    Whether type is optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var isOptional: Bool
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Whether type is implicitly unwrapped optional

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var isImplicitlyUnwrappedOptional: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + unwrappedTypeName + +
    +
    +
    +
    +
    +
    +

    Type name without attributes and optional type information

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var unwrappedTypeName: String
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Types.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Types.html new file mode 100644 index 0000000..7ec861d --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/Types.html @@ -0,0 +1,809 @@ + + + + Types Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+

Types

+ +
+
+
+
    +
  • +
    + + + + Types + +
    +
    +
    +
    +
    +
    +

    Collection of scanned types for accessing in templates

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class Types: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Type + +
    +
    +
    +
    +
    +
    +

    Defines Swift type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public class Type: NSObject, SourceryModel, Annotated
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Protocol + +
    +
    +
    +
    +
    +
    +

    Describes Swift protocol

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class Protocol: Type
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Class + +
    +
    +
    +
    +
    +
    +

    Descibes Swift class

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objc(SwiftClass) @objcMembers public final class Class: Type
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Struct + +
    +
    +
    +
    +
    +
    +

    Describes Swift struct

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class Struct: Type
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Enum + +
    +
    +
    +
    +
    +
    +

    Defines Swift enum

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class Enum: Type
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EnumCase + +
    +
    +
    +
    +
    +
    +

    Defines enum case

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + AssociatedValue + +
    +
    +
    +
    +
    +
    +

    Defines enum case associated value

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Variable + +
    +
    +
    +
    +
    +
    +

    Defines variable

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class Variable: NSObject, SourceryModel, Typed, Annotated, Definition
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Method + +
    +
    +
    +
    +
    +
    +

    Describes method

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objc(SwiftMethod) @objcMembers public final class Method: NSObject, SourceryModel, Annotated, Definition
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + MethodParameter + +
    +
    +
    +
    +
    +
    +

    Describes method parameter

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class MethodParameter: NSObject, SourceryModel, Typed, Annotated
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Subscript + +
    +
    +
    +
    +
    +
    +

    Describes subscript

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class Subscript: NSObject, SourceryModel, Annotated, Definition
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + TypeName + +
    +
    +
    +
    +
    +
    +

    Describes name of the type used in typed declaration (variable, method parameter or return value etc.)

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class TypeName: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, LosslessStringConvertible
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + TupleType + +
    +
    +
    +
    +
    +
    +

    Describes tuple type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class TupleType: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + TupleElement + +
    +
    +
    +
    +
    +
    +

    Describes tuple type element

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class TupleElement: NSObject, SourceryModel, Typed
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + ArrayType + +
    +
    +
    +
    +
    +
    +

    Describes array type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class ArrayType: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + DictionaryType + +
    +
    +
    +
    +
    +
    +

    Describes dictionary type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class DictionaryType: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + ClosureType + +
    +
    +
    +
    +
    +
    +

    Describes closure type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class ClosureType: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + GenericType + +
    +
    +
    +
    +
    +
    +

    Descibes Swift generic type

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class GenericType: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + GenericTypeParameter + +
    +
    +
    +
    +
    +
    +

    Descibes Swift generic type parameter

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public final class GenericTypeParameter: NSObject, SourceryModel
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + Attribute + +
    +
    +
    +
    +
    +
    +

    Describes Swift attribute

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objcMembers public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/badge.svg b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/badge.svg new file mode 100644 index 0000000..86e9d2b --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/badge.svg @@ -0,0 +1 @@ +documentationdocumentation100%100% \ No newline at end of file diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/codable.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/codable.html new file mode 100644 index 0000000..b294c40 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/codable.html @@ -0,0 +1,399 @@ + + + + Codable Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

I want to generate Codable implementation

+ +

This template generates Codable implementation for structs that implement AutoCodable, AutoDecodable or AutoEncodable protocols. You should define these protocols as follows:

+
protocol AutoDecodable: Decodable {}
+protocol AutoEncodable: Encodable {}
+protocol AutoCodable: AutoDecodable, AutoEncodable {}
+
+

Swift template

+

Generating coding keys.

+ +

If you have few keys that are not matching default key strategy you have to specify only these keys, all other keys will be generated and inlined by the template:

+
struct Person: AutoDecodable {
+    let id: String
+    let firstName: Bool
+    let surname: String
+
+    enum CodingKeys: String, CodingKey {
+        // this is the custom key that you define manually
+        case firstName = "first_name"
+
+// sourcery:inline:auto:Person.CodingKeys.AutoCodable
+        // the rest is generated by the template
+        case id
+        case surname
+// sourcery:end
+    }
+
+}
+
+ +

Computed properties are not encoded by default, but if you define a coding key for computed property, template will generate code that will encode it.

+ +

If you don’t define any keys manually the template will generate CodingKeys enum with the keys for all stored properties, but only if custom implementation of init(from:) or encode(to:) is needed.

+

Generating init(from:) constructor.

+ +

Template will generate implementation of init(from:) when needed. You can define additional methods and properties on your type to be used to decode it.

+ +
    +
  • method to get decoding container. This is useful if your type needs to be decoded from a nested key(s):
  • +
+
struct MyStruct: AutoDecodable {
+    let value: Int
+
+    enum CodingKeys: String, CodingKey {
+        case nested
+        case value
+    }
+
+    static func decodingContainer(_ decoder: Decoder) throws -> KeyedDecodingContainer<CodingKeys> {
+        return try decoder.container(keyedBy: CodingKeys.self)
+            .nestedContainer(keyedBy: CodingKeys.self, forKey: .nested)
+    }
+}
+
+ +
    +
  • method to decode a property. This is useful if you need to decode some property manually:
  • +
+
struct MyStruct: AutoDecodable {
+    let myProperty: Int
+
+    static func decodeMyProperty(from container: KeyedDecodingContainer<CodingKeys>) -> Int? {
+        return (try? container.decode(String.self, forKey: .myProperty)).flatMap(Int.init)
+    }
+    //or
+    static func decodeMyProperty(from decoder: Decoder) throws -> Int {
+        return try decoder.container(keyedBy: CodingKeys.self)
+            .decode(Int.self, forKey: .myProperty)
+    }
+}
+
+ +

These methods can throw or not and can return optional or non-optional result.

+ +
    +
  • default property value. You can define a static variable that will be used as a default value of a property if decoding results in nil value:
  • +
+
struct MyStruct: AutoDecodable {
+    let myProperty: Int
+
+    static let defaultMyProperty: Int = 0
+}
+
+

Generating encode(to:) method.

+ +

Template will generate implementation of encode(to:) method when needed. You can define additional methods to be used to encode it.

+ +
    +
  • method to get encoding container. This is useful if your type needs to be encoded into a nested key(s):
  • +
+
struct MyStruct: AutoDecodable {
+    let value: Int
+
+    enum CodingKeys: String, CodingKey {
+        case nested
+        case value
+    }
+
+    func encodingContainer(_ encoder: Encoder) -> KeyedEncodingContainer<CodingKeys> {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        return container.nestedContainer(keyedBy: CodingKeys.self, forKey: .nested)
+    }
+}
+
+ +
    +
  • method to encode a property. This is useful when you need to manually encode a property:
  • +
+
struct MyStruct: AutoDecodable {
+    let myProperty: Int
+
+    func encodeMyProperty(to container: inout KeyedEncodingContainer<CodingKeys>) {
+        try? container.decode(String(myProperty), forKey: .myProperty)
+    }
+    //or
+    func encodeMyProperty(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(String(myProperty), forKey: .myProperty)
+    }
+}
+
+ +

These methods may throw or not.

+ +

If you need to manually encode computed property and you have defined custom encoding method for it, template will generate a coding key for it too, so you don’t have to define it manually (though you may still need to define it if it needs custom raw value).

+ +
    +
  • method to encode any additional values. This is useful when you need to encode computed properties or constant values:
  • +
+
struct MyStruct: AutoDecodable {
+
+    func encodeAdditionalValues(to container: inout KeyedEncodingContainer<CodingKeys>) throws {
+        ...
+    }
+    // or
+    func encodeAdditionalValues(to encoder: Encoder) throws {
+        ...
+    }
+}
+
+ +

This method will be called in the end of generated encoding method.

+ +
    +
  • enum SkipEncodingKeys for keys to be skipped during encoding. This is useful when you have stored properties that you don’t want to encode, i.e. constants:
  • +
+
  struct MyStruct: AutoCodable {
+      let value: Int
+      let skipValue: Int
+
+      enum SkipEncodingKeys {
+          case skipValue
+      }
+  }
+
+

Codable enums

+ +

Enums with numeric or string raw values are Codable by default. For enums with no raw value or with associated values template will generate Codable implementation.

+

Enums with no raw values and no associated values

+ +

For such enums template will generate decoding/encoding code that will expect values in JSON to be exactly the same as cases’ names.

+
enum SimpleEnum: AutoDecodable {
+  case someCase
+  case anotherCase
+}
+
+ +

For such enum template will generate code that will successfully decode from/encode to JSON of following form:

+
{
+  "value": "someCase"
+  "anotherValue": "anotherCase"
+}
+
+ +

You can define coding keys to change the values:

+
enum SimpleEnum: AutoDecodable {
+  case someCase
+  case anotherCase
+
+  enum CodingKeys: String, CodingKey {
+    case someCase = "some_case"
+    case anotherCase = "another_case"
+  }
+}
+
+

Enums with assoicated values

+ +

Template supports two different representations of such enums in JSON format.

+
enum SimpleEnum: AutoDecodable {
+  case someCase(id: Int, name: String)
+  case anotherCase
+}
+
+ +

If you define a coding key named enumCaseKey then the template will generate code that will encode/decode enum in/from following format:

+
{
+  "type": "someCase" // enum case is encoded in a special key
+  "id": 1,
+  "name": "John"
+}
+
+ +

All enum cases associated values must be named.

+ +

If you don’t define enumCaseKey then the template will generate code that will encode/decode enum in/from following format:

+
{
+  "someCase": {
+    "id": 1,
+    "name": "John"
+  }
+}
+
+ +

Associated values of each enum case must be either all named or all unnamed. +For cases with unnamed associated values JSON format will use array instead of dictionary for associated values, in the same order in which they are defined:

+
{
+  "someCase": [
+    1,
+    "Jhon"
+  ]
+}
+
+ +

You can use all other customisation methods described for structs to decode/encode enum case associated values individually.

+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/css/highlight.css b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/css/highlight.css new file mode 100644 index 0000000..d0db0e1 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/css/highlight.css @@ -0,0 +1,200 @@ +/* Credit to https://gist.github.com/wataru420/2048287 */ +.highlight { + /* Comment */ + /* Error */ + /* Keyword */ + /* Operator */ + /* Comment.Multiline */ + /* Comment.Preproc */ + /* Comment.Single */ + /* Comment.Special */ + /* Generic.Deleted */ + /* Generic.Deleted.Specific */ + /* Generic.Emph */ + /* Generic.Error */ + /* Generic.Heading */ + /* Generic.Inserted */ + /* Generic.Inserted.Specific */ + /* Generic.Output */ + /* Generic.Prompt */ + /* Generic.Strong */ + /* Generic.Subheading */ + /* Generic.Traceback */ + /* Keyword.Constant */ + /* Keyword.Declaration */ + /* Keyword.Pseudo */ + /* Keyword.Reserved */ + /* Keyword.Type */ + /* Literal.Number */ + /* Literal.String */ + /* Name.Attribute */ + /* Name.Builtin */ + /* Name.Class */ + /* Name.Constant */ + /* Name.Entity */ + /* Name.Exception */ + /* Name.Function */ + /* Name.Namespace */ + /* Name.Tag */ + /* Name.Variable */ + /* Operator.Word */ + /* Text.Whitespace */ + /* Literal.Number.Float */ + /* Literal.Number.Hex */ + /* Literal.Number.Integer */ + /* Literal.Number.Oct */ + /* Literal.String.Backtick */ + /* Literal.String.Char */ + /* Literal.String.Doc */ + /* Literal.String.Double */ + /* Literal.String.Escape */ + /* Literal.String.Heredoc */ + /* Literal.String.Interpol */ + /* Literal.String.Other */ + /* Literal.String.Regex */ + /* Literal.String.Single */ + /* Literal.String.Symbol */ + /* Name.Builtin.Pseudo */ + /* Name.Variable.Class */ + /* Name.Variable.Global */ + /* Name.Variable.Instance */ + /* Literal.Number.Integer.Long */ } + .highlight .c { + color: #999988; + font-style: italic; } + .highlight .err { + color: #a61717; + background-color: #e3d2d2; } + .highlight .k { + color: #000000; + font-weight: bold; } + .highlight .o { + color: #000000; + font-weight: bold; } + .highlight .cm { + color: #999988; + font-style: italic; } + .highlight .cp { + color: #999999; + font-weight: bold; } + .highlight .c1 { + color: #999988; + font-style: italic; } + .highlight .cs { + color: #999999; + font-weight: bold; + font-style: italic; } + .highlight .gd { + color: #000000; + background-color: #ffdddd; } + .highlight .gd .x { + color: #000000; + background-color: #ffaaaa; } + .highlight .ge { + color: #000000; + font-style: italic; } + .highlight .gr { + color: #aa0000; } + .highlight .gh { + color: #999999; } + .highlight .gi { + color: #000000; + background-color: #ddffdd; } + .highlight .gi .x { + color: #000000; + background-color: #aaffaa; } + .highlight .go { + color: #888888; } + .highlight .gp { + color: #555555; } + .highlight .gs { + font-weight: bold; } + .highlight .gu { + color: #aaaaaa; } + .highlight .gt { + color: #aa0000; } + .highlight .kc { + color: #000000; + font-weight: bold; } + .highlight .kd { + color: #000000; + font-weight: bold; } + .highlight .kp { + color: #000000; + font-weight: bold; } + .highlight .kr { + color: #000000; + font-weight: bold; } + .highlight .kt { + color: #445588; } + .highlight .m { + color: #009999; } + .highlight .s { + color: #d14; } + .highlight .na { + color: #008080; } + .highlight .nb { + color: #0086B3; } + .highlight .nc { + color: #445588; + font-weight: bold; } + .highlight .no { + color: #008080; } + .highlight .ni { + color: #800080; } + .highlight .ne { + color: #990000; + font-weight: bold; } + .highlight .nf { + color: #990000; } + .highlight .nn { + color: #555555; } + .highlight .nt { + color: #000080; } + .highlight .nv { + color: #008080; } + .highlight .ow { + color: #000000; + font-weight: bold; } + .highlight .w { + color: #bbbbbb; } + .highlight .mf { + color: #009999; } + .highlight .mh { + color: #009999; } + .highlight .mi { + color: #009999; } + .highlight .mo { + color: #009999; } + .highlight .sb { + color: #d14; } + .highlight .sc { + color: #d14; } + .highlight .sd { + color: #d14; } + .highlight .s2 { + color: #d14; } + .highlight .se { + color: #d14; } + .highlight .sh { + color: #d14; } + .highlight .si { + color: #d14; } + .highlight .sx { + color: #d14; } + .highlight .sr { + color: #009926; } + .highlight .s1 { + color: #d14; } + .highlight .ss { + color: #990073; } + .highlight .bp { + color: #999999; } + .highlight .vc { + color: #008080; } + .highlight .vg { + color: #008080; } + .highlight .vi { + color: #008080; } + .highlight .il { + color: #009999; } diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/css/jazzy.css b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/css/jazzy.css new file mode 100644 index 0000000..d628282 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/css/jazzy.css @@ -0,0 +1,337 @@ +html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { + background: transparent; + border: 0; + margin: 0; + outline: 0; + padding: 0; + vertical-align: baseline; } + +body { + background-color: #f2f2f2; + font-family: Helvetica, freesans, Arial, sans-serif; + font-size: 14px; + -webkit-font-smoothing: subpixel-antialiased; + word-wrap: break-word; } + +h1, h2, h3 { + margin-top: 0.8em; + margin-bottom: 0.3em; + font-weight: 100; + color: black; } + +h1 { + font-size: 2.5em; } + +h2 { + font-size: 2em; + border-bottom: 1px solid #e2e2e2; } + +h4 { + font-size: 13px; + line-height: 1.5; + margin-top: 21px; } + +h5 { + font-size: 1.1em; } + +h6 { + font-size: 1.1em; + color: #777; } + +.section-name { + color: gray; + display: block; + font-family: Helvetica; + font-size: 22px; + font-weight: 100; + margin-bottom: 15px; } + +pre, code { + font: 0.95em Menlo, monospace; + color: #777; + word-wrap: normal; } + +p code, li code { + background-color: #eee; + padding: 2px 4px; + border-radius: 4px; } + +a { + color: #0088cc; + text-decoration: none; } + +ul { + padding-left: 15px; } + +li { + line-height: 1.8em; } + +img { + max-width: 100%; } + +blockquote { + margin-left: 0; + padding: 0 10px; + border-left: 4px solid #ccc; } + +.content-wrapper { + margin: 0 auto; + width: 980px; } + +header { + font-size: 0.85em; + line-height: 26px; + background-color: #414141; + position: fixed; + width: 100%; + z-index: 1; } + header img { + padding-right: 6px; + vertical-align: -4px; + height: 16px; } + header a { + color: #fff; } + header p { + float: left; + color: #999; } + header .header-right { + float: right; + margin-left: 16px; } + +#breadcrumbs { + background-color: #f2f2f2; + height: 27px; + padding-top: 17px; + position: fixed; + width: 100%; + z-index: 1; + margin-top: 26px; } + #breadcrumbs #carat { + height: 10px; + margin: 0 5px; } + +.sidebar { + background-color: #f9f9f9; + border: 1px solid #e2e2e2; + overflow-y: auto; + overflow-x: hidden; + position: fixed; + top: 70px; + bottom: 0; + width: 230px; + word-wrap: normal; } + +.nav-groups { + list-style-type: none; + background: #fff; + padding-left: 0; } + +.nav-group-name { + border-bottom: 1px solid #e2e2e2; + font-size: 1.1em; + font-weight: 100; + padding: 15px 0 15px 20px; } + .nav-group-name > a { + color: #333; } + +.nav-group-tasks { + margin-top: 5px; } + +.nav-group-task { + font-size: 0.9em; + list-style-type: none; + white-space: nowrap; } + .nav-group-task a { + color: #888; } + +.main-content { + background-color: #fff; + border: 1px solid #e2e2e2; + margin-left: 246px; + position: absolute; + overflow: hidden; + padding-bottom: 60px; + top: 70px; + width: 734px; } + .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { + margin-bottom: 1em; } + .main-content p { + line-height: 1.8em; } + .main-content section .section:first-child { + margin-top: 0; + padding-top: 0; } + .main-content section .task-group-section .task-group:first-of-type { + padding-top: 10px; } + .main-content section .task-group-section .task-group:first-of-type .section-name { + padding-top: 15px; } + .main-content section .heading:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + +.section { + padding: 0 25px; } + +.highlight { + background-color: #eee; + padding: 10px 12px; + border: 1px solid #e2e2e2; + border-radius: 4px; + overflow-x: auto; } + +.declaration .highlight { + overflow-x: initial; + padding: 0 40px 40px 0; + margin-bottom: -25px; + background-color: transparent; + border: none; } + +.section-name { + margin: 0; + margin-left: 18px; } + +.task-group-section { + padding-left: 6px; + border-top: 1px solid #e2e2e2; } + +.task-group { + padding-top: 0px; } + +.task-name-container a[name]:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + +.item { + padding-top: 8px; + width: 100%; + list-style-type: none; } + .item a[name]:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + .item code { + background-color: transparent; + padding: 0; } + .item .token { + padding-left: 3px; + margin-left: 15px; + font-size: 11.9px; } + .item .declaration-note { + font-size: .85em; + color: gray; + font-style: italic; } + +.pointer-container { + border-bottom: 1px solid #e2e2e2; + left: -23px; + padding-bottom: 13px; + position: relative; + width: 110%; } + +.pointer { + background: #f9f9f9; + border-left: 1px solid #e2e2e2; + border-top: 1px solid #e2e2e2; + height: 12px; + left: 21px; + top: -7px; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + width: 12px; } + +.height-container { + display: none; + left: -25px; + padding: 0 25px; + position: relative; + width: 100%; + overflow: hidden; } + .height-container .section { + background: #f9f9f9; + border-bottom: 1px solid #e2e2e2; + left: -25px; + position: relative; + width: 100%; + padding-top: 10px; + padding-bottom: 5px; } + +.aside, .language { + padding: 6px 12px; + margin: 12px 0; + border-left: 5px solid #dddddd; + overflow-y: hidden; } + .aside .aside-title, .language .aside-title { + font-size: 9px; + letter-spacing: 2px; + text-transform: uppercase; + padding-bottom: 0; + margin: 0; + color: #aaa; + -webkit-user-select: none; } + .aside p:last-child, .language p:last-child { + margin-bottom: 0; } + +.language { + border-left: 5px solid #cde9f4; } + .language .aside-title { + color: #4b8afb; } + +.aside-warning { + border-left: 5px solid #ff6666; } + .aside-warning .aside-title { + color: #ff0000; } + +.graybox { + border-collapse: collapse; + width: 100%; } + .graybox p { + margin: 0; + word-break: break-word; + min-width: 50px; } + .graybox td { + border: 1px solid #e2e2e2; + padding: 5px 25px 5px 10px; + vertical-align: middle; } + .graybox tr td:first-of-type { + text-align: right; + padding: 7px; + vertical-align: top; + word-break: normal; + width: 40px; } + +.slightly-smaller { + font-size: 0.9em; } + +#footer { + position: absolute; + bottom: 10px; + margin-left: 25px; } + #footer p { + margin: 0; + color: #aaa; + font-size: 0.8em; } + +html.dash header, html.dash #breadcrumbs, html.dash .sidebar { + display: none; } +html.dash .main-content { + width: 980px; + margin-left: 0; + border: none; + width: 100%; + top: 0; + padding-bottom: 0; } +html.dash .height-container { + display: block; } +html.dash .item .token { + margin-left: 0; } +html.dash .content-wrapper { + width: auto; } +html.dash #footer { + position: static; } diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/decorator.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/decorator.html new file mode 100644 index 0000000..15557c8 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/decorator.html @@ -0,0 +1,256 @@ + + + + Decorator Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

I want to generate simple decorator for my type

+ +

In Swift it can be cumbersome to write a simple decorator that decorates all the calls to decorated type methods, you basically have to do it manually for each single method. With this template you can generate simple decorator that generate all the methods and property calls automatically, skipping methods and properties already implemented manually.

+ +

You can use this template as a starting point for mor sophisticated implementations. This template also shows you some powers of swift templates, like using helper methods and whitespace control tags.

+

Swift template

+

Available annotations

+ +
    +
  • decorate - what type to decorate
  • +
  • decorateMethod - code to decorate each method call with
  • +
  • decorateGet - code to decorate each property getter
  • +
  • decorateSet - code to decorate each property setter
  • +
+ +

Example input:

+
protocol Service {
+    var prop1: Int { get }
+    var prop2: Int { get set }
+    func foo(f: Int, _ a: Int) throws -> Int
+    func bar(_ b: String)
+}
+
+// sourcery: decorate = "Service"
+// sourcery: decorateMethod = "print(#function)"
+// sourcery: decorateGet = "print("get: \(#function)")"
+// sourcery: decorateSet = "print("set: \(#function)")"
+struct ServiceDecorator: Service {
+    // generated code will go here
+}
+
+extension ServiceDecorator {
+     // manually implemented method
+    internal func bar(_ b: String) {
+        decorated.bar(b)
+    }
+
+}
+
+
+ +

Example output:

+
...
+
+// sourcery: decorate = Service
+// sourcery: decorateMethod = print(#function)
+// sourcery: decorateGet = "print("get: \(#function)")"
+// sourcery: decorateSet = "print("set: \(#function)")"
+struct ServiceDecorator: Service {
+
+// sourcery:inline:auto:ServiceDecorator.autoDecorated
+    internal private(set) var decorated: Service
+
+    internal init(decorated: Service) {
+        self.decorated = decorated
+    }
+
+    internal var prop1: Int {
+        print("get: \(#function)")
+        return decorated.prop1
+    }
+
+    internal var prop2: Int {
+        get {
+            print("get: \(#function)")
+            return decorated.prop2
+        }
+        set {
+            print("set: \(#function)")
+            decorated.prop2 = newValue
+        }
+    }
+
+    internal func foo(f: Int, _ a: Int) throws -> Int {
+        print(#function)
+        return try decorated.foo(f: f, a)
+    }
+// sourcery:end
+}
+...
+
+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/diffable.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/diffable.html new file mode 100644 index 0000000..1773b9c --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/diffable.html @@ -0,0 +1,190 @@ + + + + Diffable Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

I want to have diffing in tests

+ +

Template used to generate much better output when using equality in tests, instead of having to read wall of text it’s used to generate precise property level differences. This template uses Sourcery Diffable implementation

+ +

from this: +before

+ +

to this: +after

+

Stencil Template

+

Available annotations:

+ +
    +
  • skipEquality allows you to skip variable from being compared.
  • +
+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/enum-cases.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/enum-cases.html new file mode 100644 index 0000000..c0f23cd --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/enum-cases.html @@ -0,0 +1,195 @@ + + + + Enum cases Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

I want to list all cases in an enum

+ +

Generate count and allCases for any enumeration that is marked with AutoCases phantom protocol.

+

Stencil Template

+

Example output:

+
extension BetaSettingsGroup {
+  static let count: Int = return 8
+
+  static let allCases: [BetaSettingsGroup] = [
+      .featuresInDevelopment,
+      .advertising,
+      .analytics,
+      .marketing,
+      .news,
+      .notifications,
+      .tech,
+      .appInformation
+    ]
+}
+
+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/equatable.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/equatable.html new file mode 100644 index 0000000..badc914 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/equatable.html @@ -0,0 +1,203 @@ + + + + Equatable Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

I want to generate Equatable implementation

+ +

Template used to generate equality for all types that either conform to the AutoEquatable protocol or are annotated with AutoEquatable annotation, allowing us to avoid writing boilerplate code.

+ +

It adds :Equatable conformance to all types, except protocols (because it would require turning them into PAT’s). +For protocols it’s just generating func ==.

+

Stencil template

+

Available variable annotations:

+ +
    +
  • skipEquality allows you to skip variable from being compared.
  • +
  • arrayEquality mark this to use array comparsion for variables that have array of items that don’t implement Equatable but have == operator e.g. Protocols
  • +
+

Example output:

+
// MARK: - AdNodeViewModel AutoEquatable
+extension AdNodeViewModel: Equatable {}
+
+internal func == (lhs: AdNodeViewModel, rhs: AdNodeViewModel) -> Bool {
+    guard lhs.remoteAdView == rhs.remoteAdView else { return false }
+    guard lhs.hidesDisclaimer == rhs.hidesDisclaimer else { return false }
+    guard lhs.type == rhs.type else { return false }
+    guard lhs.height == rhs.height else { return false }
+
+    guard lhs.attributedDisclaimer == rhs.attributedDisclaimer else { return false }
+
+    return true
+}
+
+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/hashable.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/hashable.html new file mode 100644 index 0000000..b3f8fa4 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/hashable.html @@ -0,0 +1,197 @@ + + + + Hashable Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

I want to generate Hashable implementation

+ +

Template used to generate hashing for all types that conform to :AutoHashable, allowing us to avoid writing boilerplate code.

+ +

It adds :Hashable conformance to all types, except protocols (because it would require turning them into PAT’s). +For protocols it’s just generating var hashValue comparator.

+

Stencil template

+

Available variable annotations:

+ +
    +
  • skipHashing allows you to skip variable from being compared.
  • +
  • includeInHashing is only applied on enums and allows us to add some computed variable into hashing logic
  • +
+

Example output:

+
// MARK: - AdNodeViewModel AutoHashable
+extension AdNodeViewModel: Hashable {
+
+    internal var hashValue: Int {
+        return combineHashes(remoteAdView.hashValue, hidesDisclaimer.hashValue, type.hashValue, height.hashValue, attributedDisclaimer.hashValue, 0)
+    }
+}
+
+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/carat.png b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/carat.png new file mode 100755 index 0000000..29d2f7f Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/carat.png differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/dash.png b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/dash.png new file mode 100755 index 0000000..6f694c7 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/dash.png differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/gh.png b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/gh.png new file mode 100755 index 0000000..628da97 Binary files /dev/null and b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/img/gh.png differ diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/index.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/index.html new file mode 100644 index 0000000..8e1accc --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/index.html @@ -0,0 +1,209 @@ + + + + Sourcery Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

What is Sourcery?

+ +

Sourcery scans your source code, applies your personal templates and generates Swift code for you, allowing you to use meta-programming techniques to save time and decrease potential mistakes.

+ +

Using it offers many benefits:

+ +
    +
  • Write less repetitive code and make it easy to adhere to DRY principle.
  • +
  • It allows you to create better code, one that would be hard to maintain without it, e.g. performing automatic property level difference in tests
  • +
  • Limits the risk of introducing human error when refactoring.
  • +
  • Sourcery doesn’t use runtime tricks, in fact, it allows you to leverage compiler, even more, creating more safety.
  • +
  • Immediate feedback: Sourcery features built-in daemon support, enabling you to write your templates in real-time side-by-side with generated code.
  • +
+ +

Sourcery is so meta that it is used to code-generate its boilerplate code

+

Why?

+ +

Swift features very limited runtime and no meta-programming features. Which leads our projects to contain boilerplate code.

+ +

Sourcery exists to allow Swift developers to stop doing the same thing over and over again while still maintaining strong typing, preventing bugs and leveraging compiler.

+ +

Have you ever?

+ +
    +
  • Had to write equatable/hashable?
  • +
  • Had to write NSCoding support?
  • +
  • Had to implement JSON serialization?
  • +
  • Wanted to use Lenses?
  • +
+ +

If you did then you probably found yourself writing repetitive code to deal with those scenarios, does this feel right?

+ +

Even worse, if you ever add a new property to a type all of those implementations have to be updated, or you will end up with bugs. +In those scenarios usually compiler will not generate the error for you, which leads to error prone code.

+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/installing.html b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/installing.html new file mode 100644 index 0000000..5641479 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/installing.html @@ -0,0 +1,201 @@ + + + + Installing Reference + + + + + + + + + +
+
+

Sourcery Docs (100% documented)

+

View on GitHub

+
+
+
+ +
+
+ +
+
+
+ +

Installing

+ +
    +
  • Binary form

    + +

    Download latest release with prebuilt binary from release tab. Unzip the archive into desired destination and run bin/sourcery

  • +
  • CocoaPods

    + +

    Add pod ‘Sourcery’ to your Podfile and run pod update Sourcery. This will download latest release binary and will put it to your project’s CocoaPods path so you will run it with $PODS_ROOT/Sourcery/bin/sourcery

  • +
  • Building from source

    + +

    Download latest release source code from release tab or clone the repository an build Sourcery manually.

    + +
      +
    • Building with Swift Package Manager

      + +

      Run swift build -c release in the root folder. This will create a .build/release folder and will put binary there. Move the whole .build/release folder to your desired destination and run with path_to_release_folder/sourcery

      + +
      +

      Note: JS templates are not supported when building with SPM yet.

      +
    • +
    • Building with Xcode

      + +

      Open Sourcery.xcworkspace and build with Sourcery-Release scheme. This will create Sourcery.app in the Derived Data folder. You can copy it to your desired destination and run with path_to_sourcery_app/Sourcery.app/Contents/MacOS/Sourcery

    • +
  • +
+ +
+
+ +
+
+ + + diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/js/jazzy.js b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/js/jazzy.js new file mode 100755 index 0000000..3965b5f --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/js/jazzy.js @@ -0,0 +1,46 @@ +window.jazzy = {'docset': false} +if (typeof window.dash != 'undefined') { + document.documentElement.className += ' dash' + window.jazzy.docset = true +} +if (navigator.userAgent.match(/xcode/i)) { + document.documentElement.className += ' xcode' + window.jazzy.docset = true +} + +// On doc load, toggle the URL hash discussion if present +$(document).ready(function() { + if (!window.jazzy.docset) { + var linkToHash = $('a[href="' + window.location.hash +'"]'); + linkToHash.trigger("click"); + } +}); + +// On token click, toggle its discussion and animate token.marginLeft +$(".token").click(function(event) { + if (window.jazzy.docset) { + return; + } + var link = $(this); + var animationDuration = 300; + var tokenOffset = "15px"; + var original = link.css('marginLeft') == tokenOffset; + link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); + $content = link.parent().parent().next(); + $content.slideToggle(animationDuration); + + // Keeps the document from jumping to the hash. + var href = $(this).attr('href'); + if (history.pushState) { + history.pushState({}, '', href); + } else { + location.hash = href; + } + event.preventDefault(); +}); + +// Dumb down quotes within code blocks that delimit strings instead of quotations +// https://github.com/realm/jazzy/issues/714 +$("code q").replaceWith(function () { + return ["\"", $(this).contents(), "\""]; +}); diff --git a/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/js/jquery.min.js b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/js/jquery.min.js new file mode 100755 index 0000000..ab28a24 --- /dev/null +++ b/{{ cookiecutter.project_name | replace(' ', '') }}/app/Pods/Sourcery/Sourcery.docset/Contents/Resources/Documents/js/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("